//@version=6
indicator("bar_index")
plot(bar_index)
plot(bar_index > 5000 ? close : 0)
//@version=6
indicator("box.all")
//delete all boxes
box.new(time, open, time + 60 * 60 * 24, close, xloc=xloc.bar_time, border_style=line.style_dashed)
a_allBoxes = box.all
if array.size(a_allBoxes) > 0
for i = 0 to array.size(a_allBoxes) - 1
box.delete(array.get(a_allBoxes, i))
//@version=6
indicator("label.all")
//delete all labels
label.new(bar_index, close)
a_allLabels = label.all
if array.size(a_allLabels) > 0
for i = 0 to array.size(a_allLabels) - 1
label.delete(array.get(a_allLabels, i))
//@version=6
strategy("Mark Last X Bars For Backtesting", overlay = true, calc_on_every_tick = true)
lastBarsFilterInput = input.int(100, "Bars Count:")
// Here, we store the 'last_bar_index' value that is known from the beginning of the script's calculation.
// The 'last_bar_index' will change when new real-time bars appear, so we declare 'lastbar' with the 'var' keyword.
var lastbar = last_bar_index
// Check if the current bar_index is 'lastBarsFilterInput' removed from the last bar on the chart, or the chart is traded in real-time.
allowedToTrade = (lastbar - bar_index <= lastBarsFilterInput) or barstate.isrealtime
bgcolor(allowedToTrade ? color.new(color.green, 80) : na)
//@version=6
indicator("line.all")
//delete all lines
line.new(bar_index - 10, close, bar_index, close)
a_allLines = line.all
if array.size(a_allLines) > 0
for i = 0 to array.size(a_allLines) - 1
line.delete(array.get(a_allLines, i))
//@version=6
indicator("na")
// CORRECT
// Plot no value when on bars zero to nine. Plot `close` on other bars.
plot(bar_index < 10 ? na : close)
// CORRECT ALTERNATIVE
// Initialize `a` to `na`. Reassign `close` to `a` on bars 10 and later.
float a = na
if bar_index >= 10
a := close
plot(a)
// INCORRECT
// Trying to test the preceding bar's `close` for `na`.
// The next line, if uncommented, will cause a compilation error, because direct comparison with `na` is not allowed.
// plot(close[1] == na ? close : close[1])
// CORRECT
// Use the `na()` function to test for `na`.
plot(na(close[1]) ? close : close[1])
// CORRECT ALTERNATIVE
// `nz()` tests `close[1]` for `na`. It returns `close[1]` if it is not `na`, and `close` if it is.
plot(nz(close[1], close))
na, as it might lead to unexpected behavior. Instead, use the na function. Note that na can be used to initialize variables when the initialization statement also specifies the variable's type.true on the first bar of the pre-market bars.//@version=6
strategy("`session.isfirstbar` Example", overlay = true)
longCondition = year >= 2022
// Place a long order at the `close` of the trading session's first bar.
if session.isfirstbar and longCondition
strategy.entry("Long", strategy.long)
// Close the long position at the `close` of the trading session's last bar.
if session.islastbar and barstate.isconfirmed
strategy.close("Long", immediately = true)
//@version=6
strategy("`session.isfirstbar_regular` Example", overlay = true)
longCondition = year >= 2022
// Place a long order at the `close` of the trading session's first bar.
if session.isfirstbar and longCondition
strategy.entry("Long", strategy.long)
// Close the long position at the `close` of the trading session's last bar.
if session.islastbar_regular and barstate.isconfirmed
strategy.close("Long", immediately = true)
true on the last bar of the post-market bars.//@version=6
strategy("`session.islastbar` Example", overlay = true)
longCondition = year >= 2022
// Place a long order at the `close` of the trading session's last bar.
// The position will enter on the `open` of next session's first bar.
if session.islastbar and longCondition
strategy.entry("Long", strategy.long)
// Close 'Long' position at the close of the last bar of the trading session
if session.islastbar and barstate.isconfirmed
strategy.close("Long", immediately = true)
//@version=6
strategy("`session.islastbar_regular` Example", overlay = true)
longCondition = year >= 2022
// Place a long order at the `close` of the trading session's first bar.
if session.isfirstbar and longCondition
strategy.entry("Long", strategy.long)
// Close the long position at the `close` of the trading session's last bar.
if session.islastbar_regular and barstate.isconfirmed
strategy.close("Long", immediately = true)
//@version=6
strategy("Margin call management", overlay = true, margin_long = 25, margin_short = 25,
default_qty_type = strategy.percent_of_equity, default_qty_value = 395)
float maFast = ta.sma(close, 14)
float maSlow = ta.sma(close, 28)
if ta.crossover(maFast, maSlow)
strategy.entry("Long", strategy.long)
if ta.crossunder(maFast, maSlow)
strategy.entry("Short", strategy.short)
changePercent(v1, v2) =>
float result = (v1 - v2) * 100 / math.abs(v2)
// exit when we're 10% away from a margin call, to prevent it.
if math.abs(changePercent(close, strategy.margin_liquidation_price)) <= 10
strategy.close("Long")
strategy.close("Short")
Lowest Value During Trade / (Entry Price x Quantity) * 100.Highest Value During Trade / (Entry Price x Quantity) * 100.openPL / realizedEquity * 100.//@version=6
strategy(
"strategy.opentrades.capital_held example", overlay=false, margin_long=50, margin_short=50,
default_qty_type = strategy.percent_of_equity, default_qty_value = 100
)
// Enter a short position on the first bar.
if barstate.isfirst
strategy.entry("Short", strategy.short)
// Plot the capital held by the short position.
plot(strategy.opentrades.capital_held, "Capital held")
// Highlight the chart background if the position is completely closed by margin calls.
bgcolor(bar_index > 0 and strategy.opentrades.capital_held == 0 ? color.new(color.red, 60) : na)
//@version=6
indicator("syminfo simple")
//@variable A table containing information about a company's employees, shareholders, and shares.
var result_table = table.new(position = position.top_right, columns = 2, rows = 5, border_width = 1)
if barstate.islastconfirmedhistory
// Add header cells
table.cell(table_id = result_table, column = 0, row = 0, text = "name")
table.cell(table_id = result_table, column = 1, row = 0, text = "value")
// Add employee info cells.
table.cell(table_id = result_table, column = 0, row = 1, text = "employees")
table.cell(table_id = result_table, column = 1, row = 1, text = str.tostring(syminfo.employees))
// Add shareholder cells.
table.cell(table_id = result_table, column = 0, row = 2, text = "shareholders")
table.cell(table_id = result_table, column = 1, row = 2, text = str.tostring(syminfo.shareholders))
// Add float shares outstanding cells.
table.cell(table_id = result_table, column = 0, row = 3, text = "shares_outstanding_float")
table.cell(table_id = result_table, column = 1, row = 3, text = str.tostring(syminfo.shares_outstanding_float))
// Add total shares outstanding cells.
table.cell(table_id = result_table, column = 0, row = 4, text = "shares_outstanding_total")
table.cell(table_id = result_table, column = 1, row = 4, text = str.tostring(syminfo.shares_outstanding_total))
expression argument of a request.*() function call.syminfo.minmove / syminfo.pricescale = syminfo.mintick.//@version=6
indicator("syminfo.prefix")
// If current chart symbol is 'BATS:MSFT' then syminfo.prefix is 'BATS'.
if barstate.islastconfirmedhistory
label.new(bar_index, high, text=syminfo.prefix)
syminfo.minmove / syminfo.pricescale = syminfo.mintick.//@version=6
indicator("syminfo recommendations", overlay = true)
//@variable A table containing information about analyst recommendations.
var table ratings = table.new(position.top_right, 8, 2, frame_color = #000000)
if barstate.islastconfirmedhistory
//@variable The time value one year from the date of the last analyst recommendations.
int YTD = syminfo.target_price_date + timeframe.in_seconds("12M") * 1000
// Add header cells.
table.cell(ratings, 0, 0, "Start Date", bgcolor = color.gray, text_color = #000000, text_size = size.large)
table.cell(ratings, 1, 0, "End Date", bgcolor = color.gray, text_color = #000000, text_size = size.large)
table.cell(ratings, 2, 0, "Buy", bgcolor = color.teal, text_color = #000000, text_size = size.large)
table.cell(ratings, 3, 0, "Strong Buy", bgcolor = color.lime, text_color = #000000, text_size = size.large)
table.cell(ratings, 4, 0, "Sell", bgcolor = color.maroon, text_color = #000000, text_size = size.large)
table.cell(ratings, 5, 0, "Strong Sell", bgcolor = color.red, text_color = #000000, text_size = size.large)
table.cell(ratings, 6, 0, "Hold", bgcolor = color.orange, text_color = #000000, text_size = size.large)
table.cell(ratings, 7, 0, "Total", bgcolor = color.silver, text_color = #000000, text_size = size.large)
// Recommendation strings
string startDate = str.format_time(syminfo.recommendations_date, "yyyy-MM-dd")
string endDate = str.format_time(YTD, "yyyy-MM-dd")
string buyRatings = str.tostring(syminfo.recommendations_buy)
string strongBuyRatings = str.tostring(syminfo.recommendations_buy_strong)
string sellRatings = str.tostring(syminfo.recommendations_sell)
string strongSellRatings = str.tostring(syminfo.recommendations_sell_strong)
string holdRatings = str.tostring(syminfo.recommendations_hold)
string totalRatings = str.tostring(syminfo.recommendations_total)
// Add value cells
table.cell(ratings, 0, 1, startDate, bgcolor = color.gray, text_color = #000000, text_size = size.large)
table.cell(ratings, 1, 1, endDate, bgcolor = color.gray, text_color = #000000, text_size = size.large)
table.cell(ratings, 2, 1, buyRatings, bgcolor = color.teal, text_color = #000000, text_size = size.large)
table.cell(ratings, 3, 1, strongBuyRatings, bgcolor = color.lime, text_color = #000000, text_size = size.large)
table.cell(ratings, 4, 1, sellRatings, bgcolor = color.maroon, text_color = #000000, text_size = size.large)
//@version=6
indicator("syminfo recommendations", overlay = true)
//@variable A table containing information about analyst recommendations.
var table ratings = table.new(position.top_right, 8, 2, frame_color = #000000)
if barstate.islastconfirmedhistory
//@variable The time value one year from the date of the last analyst recommendations.
int YTD = syminfo.target_price_date + timeframe.in_seconds("12M") * 1000
// Add header cells.
table.cell(ratings, 0, 0, "Start Date", bgcolor = color.gray, text_color = #000000, text_size = size.large)
table.cell(ratings, 1, 0, "End Date", bgcolor = color.gray, text_color = #000000, text_size = size.large)
table.cell(ratings, 2, 0, "Buy", bgcolor = color.teal, text_color = #000000, text_size = size.large)
table.cell(ratings, 3, 0, "Strong Buy", bgcolor = color.lime, text_color = #000000, text_size = size.large)
table.cell(ratings, 4, 0, "Sell", bgcolor = color.maroon, text_color = #000000, text_size = size.large)
table.cell(ratings, 5, 0, "Strong Sell", bgcolor = color.red, text_color = #000000, text_size = size.large)
table.cell(ratings, 6, 0, "Hold", bgcolor = color.orange, text_color = #000000, text_size = size.large)
table.cell(ratings, 7, 0, "Total", bgcolor = color.silver, text_color = #000000, text_size = size.large)
// Recommendation strings
string startDate = str.format_time(syminfo.recommendations_date, "yyyy-MM-dd")
string endDate = str.format_time(YTD, "yyyy-MM-dd")
string buyRatings = str.tostring(syminfo.recommendations_buy)
string strongBuyRatings = str.tostring(syminfo.recommendations_buy_strong)
string sellRatings = str.tostring(syminfo.recommendations_sell)
string strongSellRatings = str.tostring(syminfo.recommendations_sell_strong)
string holdRatings = str.tostring(syminfo.recommendations_hold)
string totalRatings = str.tostring(syminfo.recommendations_total)
// Add value cells
table.cell(ratings, 0, 1, startDate, bgcolor = color.gray, text_color = #000000, text_size = size.large)
table.cell(ratings, 1, 1, endDate, bgcolor = color.gray, text_color = #000000, text_size = size.large)
table.cell(ratings, 2, 1, buyRatings, bgcolor = color.teal, text_color = #000000, text_size = size.large)
table.cell(ratings, 3, 1, strongBuyRatings, bgcolor = color.lime, text_color = #000000, text_size = size.large)
table.cell(ratings, 4, 1, sellRatings, bgcolor = color.maroon, text_color = #000000, text_size = size.large)
//@version=6
indicator("syminfo recommendations", overlay = true)
//@variable A table containing information about analyst recommendations.
var table ratings = table.new(position.top_right, 8, 2, frame_color = #000000)
if barstate.islastconfirmedhistory
//@variable The time value one year from the date of the last analyst recommendations.
int YTD = syminfo.target_price_date + timeframe.in_seconds("12M") * 1000
// Add header cells.
table.cell(ratings, 0, 0, "Start Date", bgcolor = color.gray, text_color = #000000, text_size = size.large)
table.cell(ratings, 1, 0, "End Date", bgcolor = color.gray, text_color = #000000, text_size = size.large)
table.cell(ratings, 2, 0, "Buy", bgcolor = color.teal, text_color = #000000, text_size = size.large)
table.cell(ratings, 3, 0, "Strong Buy", bgcolor = color.lime, text_color = #000000, text_size = size.large)
table.cell(ratings, 4, 0, "Sell", bgcolor = color.maroon, text_color = #000000, text_size = size.large)
table.cell(ratings, 5, 0, "Strong Sell", bgcolor = color.red, text_color = #000000, text_size = size.large)
table.cell(ratings, 6, 0, "Hold", bgcolor = color.orange, text_color = #000000, text_size = size.large)
table.cell(ratings, 7, 0, "Total", bgcolor = color.silver, text_color = #000000, text_size = size.large)
// Recommendation strings
string startDate = str.format_time(syminfo.recommendations_date, "yyyy-MM-dd")
string endDate = str.format_time(YTD, "yyyy-MM-dd")
string buyRatings = str.tostring(syminfo.recommendations_buy)
string strongBuyRatings = str.tostring(syminfo.recommendations_buy_strong)
string sellRatings = str.tostring(syminfo.recommendations_sell)
string strongSellRatings = str.tostring(syminfo.recommendations_sell_strong)
string holdRatings = str.tostring(syminfo.recommendations_hold)
string totalRatings = str.tostring(syminfo.recommendations_total)
// Add value cells
table.cell(ratings, 0, 1, startDate, bgcolor = color.gray, text_color = #000000, text_size = size.large)
table.cell(ratings, 1, 1, endDate, bgcolor = color.gray, text_color = #000000, text_size = size.large)
table.cell(ratings, 2, 1, buyRatings, bgcolor = color.teal, text_color = #000000, text_size = size.large)
table.cell(ratings, 3, 1, strongBuyRatings, bgcolor = color.lime, text_color = #000000, text_size = size.large)
table.cell(ratings, 4, 1, sellRatings, bgcolor = color.maroon, text_color = #000000, text_size = size.large)
//@version=6
indicator("syminfo recommendations", overlay = true)
//@variable A table containing information about analyst recommendations.
var table ratings = table.new(position.top_right, 8, 2, frame_color = #000000)
if barstate.islastconfirmedhistory
//@variable The time value one year from the date of the last analyst recommendations.
int YTD = syminfo.target_price_date + timeframe.in_seconds("12M") * 1000
// Add header cells.
table.cell(ratings, 0, 0, "Start Date", bgcolor = color.gray, text_color = #000000, text_size = size.large)
table.cell(ratings, 1, 0, "End Date", bgcolor = color.gray, text_color = #000000, text_size = size.large)
table.cell(ratings, 2, 0, "Buy", bgcolor = color.teal, text_color = #000000, text_size = size.large)
table.cell(ratings, 3, 0, "Strong Buy", bgcolor = color.lime, text_color = #000000, text_size = size.large)
table.cell(ratings, 4, 0, "Sell", bgcolor = color.maroon, text_color = #000000, text_size = size.large)
table.cell(ratings, 5, 0, "Strong Sell", bgcolor = color.red, text_color = #000000, text_size = size.large)
table.cell(ratings, 6, 0, "Hold", bgcolor = color.orange, text_color = #000000, text_size = size.large)
table.cell(ratings, 7, 0, "Total", bgcolor = color.silver, text_color = #000000, text_size = size.large)
// Recommendation strings
string startDate = str.format_time(syminfo.recommendations_date, "yyyy-MM-dd")
string endDate = str.format_time(YTD, "yyyy-MM-dd")
string buyRatings = str.tostring(syminfo.recommendations_buy)
string strongBuyRatings = str.tostring(syminfo.recommendations_buy_strong)
string sellRatings = str.tostring(syminfo.recommendations_sell)
string strongSellRatings = str.tostring(syminfo.recommendations_sell_strong)
string holdRatings = str.tostring(syminfo.recommendations_hold)
string totalRatings = str.tostring(syminfo.recommendations_total)
// Add value cells
table.cell(ratings, 0, 1, startDate, bgcolor = color.gray, text_color = #000000, text_size = size.large)
table.cell(ratings, 1, 1, endDate, bgcolor = color.gray, text_color = #000000, text_size = size.large)
table.cell(ratings, 2, 1, buyRatings, bgcolor = color.teal, text_color = #000000, text_size = size.large)
table.cell(ratings, 3, 1, strongBuyRatings, bgcolor = color.lime, text_color = #000000, text_size = size.large)
table.cell(ratings, 4, 1, sellRatings, bgcolor = color.maroon, text_color = #000000, text_size = size.large)
//@version=6
indicator("syminfo recommendations", overlay = true)
//@variable A table containing information about analyst recommendations.
var table ratings = table.new(position.top_right, 8, 2, frame_color = #000000)
if barstate.islastconfirmedhistory
//@variable The time value one year from the date of the last analyst recommendations.
int YTD = syminfo.target_price_date + timeframe.in_seconds("12M") * 1000
// Add header cells.
table.cell(ratings, 0, 0, "Start Date", bgcolor = color.gray, text_color = #000000, text_size = size.large)
table.cell(ratings, 1, 0, "End Date", bgcolor = color.gray, text_color = #000000, text_size = size.large)
table.cell(ratings, 2, 0, "Buy", bgcolor = color.teal, text_color = #000000, text_size = size.large)
table.cell(ratings, 3, 0, "Strong Buy", bgcolor = color.lime, text_color = #000000, text_size = size.large)
table.cell(ratings, 4, 0, "Sell", bgcolor = color.maroon, text_color = #000000, text_size = size.large)
table.cell(ratings, 5, 0, "Strong Sell", bgcolor = color.red, text_color = #000000, text_size = size.large)
table.cell(ratings, 6, 0, "Hold", bgcolor = color.orange, text_color = #000000, text_size = size.large)
table.cell(ratings, 7, 0, "Total", bgcolor = color.silver, text_color = #000000, text_size = size.large)
// Recommendation strings
string startDate = str.format_time(syminfo.recommendations_date, "yyyy-MM-dd")
string endDate = str.format_time(YTD, "yyyy-MM-dd")
string buyRatings = str.tostring(syminfo.recommendations_buy)
string strongBuyRatings = str.tostring(syminfo.recommendations_buy_strong)
string sellRatings = str.tostring(syminfo.recommendations_sell)
string strongSellRatings = str.tostring(syminfo.recommendations_sell_strong)
string holdRatings = str.tostring(syminfo.recommendations_hold)
string totalRatings = str.tostring(syminfo.recommendations_total)
// Add value cells
table.cell(ratings, 0, 1, startDate, bgcolor = color.gray, text_color = #000000, text_size = size.large)
table.cell(ratings, 1, 1, endDate, bgcolor = color.gray, text_color = #000000, text_size = size.large)
table.cell(ratings, 2, 1, buyRatings, bgcolor = color.teal, text_color = #000000, text_size = size.large)
table.cell(ratings, 3, 1, strongBuyRatings, bgcolor = color.lime, text_color = #000000, text_size = size.large)
table.cell(ratings, 4, 1, sellRatings, bgcolor = color.maroon, text_color = #000000, text_size = size.large)
//@version=6
indicator("syminfo recommendations", overlay = true)
//@variable A table containing information about analyst recommendations.
var table ratings = table.new(position.top_right, 8, 2, frame_color = #000000)
if barstate.islastconfirmedhistory
//@variable The time value one year from the date of the last analyst recommendations.
int YTD = syminfo.target_price_date + timeframe.in_seconds("12M") * 1000
// Add header cells.
table.cell(ratings, 0, 0, "Start Date", bgcolor = color.gray, text_color = #000000, text_size = size.large)
table.cell(ratings, 1, 0, "End Date", bgcolor = color.gray, text_color = #000000, text_size = size.large)
table.cell(ratings, 2, 0, "Buy", bgcolor = color.teal, text_color = #000000, text_size = size.large)
table.cell(ratings, 3, 0, "Strong Buy", bgcolor = color.lime, text_color = #000000, text_size = size.large)
table.cell(ratings, 4, 0, "Sell", bgcolor = color.maroon, text_color = #000000, text_size = size.large)
table.cell(ratings, 5, 0, "Strong Sell", bgcolor = color.red, text_color = #000000, text_size = size.large)
table.cell(ratings, 6, 0, "Hold", bgcolor = color.orange, text_color = #000000, text_size = size.large)
table.cell(ratings, 7, 0, "Total", bgcolor = color.silver, text_color = #000000, text_size = size.large)
// Recommendation strings
string startDate = str.format_time(syminfo.recommendations_date, "yyyy-MM-dd")
string endDate = str.format_time(YTD, "yyyy-MM-dd")
string buyRatings = str.tostring(syminfo.recommendations_buy)
string strongBuyRatings = str.tostring(syminfo.recommendations_buy_strong)
string sellRatings = str.tostring(syminfo.recommendations_sell)
string strongSellRatings = str.tostring(syminfo.recommendations_sell_strong)
string holdRatings = str.tostring(syminfo.recommendations_hold)
string totalRatings = str.tostring(syminfo.recommendations_total)
// Add value cells
table.cell(ratings, 0, 1, startDate, bgcolor = color.gray, text_color = #000000, text_size = size.large)
table.cell(ratings, 1, 1, endDate, bgcolor = color.gray, text_color = #000000, text_size = size.large)
table.cell(ratings, 2, 1, buyRatings, bgcolor = color.teal, text_color = #000000, text_size = size.large)
table.cell(ratings, 3, 1, strongBuyRatings, bgcolor = color.lime, text_color = #000000, text_size = size.large)
table.cell(ratings, 4, 1, sellRatings, bgcolor = color.maroon, text_color = #000000, text_size = size.large)
//@version=6
indicator("syminfo recommendations", overlay = true)
//@variable A table containing information about analyst recommendations.
var table ratings = table.new(position.top_right, 8, 2, frame_color = #000000)
if barstate.islastconfirmedhistory
//@variable The time value one year from the date of the last analyst recommendations.
int YTD = syminfo.target_price_date + timeframe.in_seconds("12M") * 1000
// Add header cells.
table.cell(ratings, 0, 0, "Start Date", bgcolor = color.gray, text_color = #000000, text_size = size.large)
table.cell(ratings, 1, 0, "End Date", bgcolor = color.gray, text_color = #000000, text_size = size.large)
table.cell(ratings, 2, 0, "Buy", bgcolor = color.teal, text_color = #000000, text_size = size.large)
table.cell(ratings, 3, 0, "Strong Buy", bgcolor = color.lime, text_color = #000000, text_size = size.large)
table.cell(ratings, 4, 0, "Sell", bgcolor = color.maroon, text_color = #000000, text_size = size.large)
table.cell(ratings, 5, 0, "Strong Sell", bgcolor = color.red, text_color = #000000, text_size = size.large)
table.cell(ratings, 6, 0, "Hold", bgcolor = color.orange, text_color = #000000, text_size = size.large)
table.cell(ratings, 7, 0, "Total", bgcolor = color.silver, text_color = #000000, text_size = size.large)
// Recommendation strings
string startDate = str.format_time(syminfo.recommendations_date, "yyyy-MM-dd")
string endDate = str.format_time(YTD, "yyyy-MM-dd")
string buyRatings = str.tostring(syminfo.recommendations_buy)
string strongBuyRatings = str.tostring(syminfo.recommendations_buy_strong)
string sellRatings = str.tostring(syminfo.recommendations_sell)
string strongSellRatings = str.tostring(syminfo.recommendations_sell_strong)
string holdRatings = str.tostring(syminfo.recommendations_hold)
string totalRatings = str.tostring(syminfo.recommendations_total)
// Add value cells
table.cell(ratings, 0, 1, startDate, bgcolor = color.gray, text_color = #000000, text_size = size.large)
table.cell(ratings, 1, 1, endDate, bgcolor = color.gray, text_color = #000000, text_size = size.large)
table.cell(ratings, 2, 1, buyRatings, bgcolor = color.teal, text_color = #000000, text_size = size.large)
table.cell(ratings, 3, 1, strongBuyRatings, bgcolor = color.lime, text_color = #000000, text_size = size.large)
table.cell(ratings, 4, 1, sellRatings, bgcolor = color.maroon, text_color = #000000, text_size = size.large)
//@version=6
indicator("syminfo.root")
// If the current chart symbol is continuous futures ('ES1!'), it would display 'ES'.
if barstate.islastconfirmedhistory
label.new(bar_index, high, syminfo.root)
//@version=6
indicator("syminfo target_price")
if barstate.islastconfirmedhistory
//@variable The time value one year from the date of the last analyst recommendations.
int YTD = syminfo.target_price_date + timeframe.in_seconds("12M") * 1000
//@variable A line connecting the current `close` to the highest yearly price estimate.
highLine = line.new(time, close, YTD, syminfo.target_price_high, color = color.green, xloc = xloc.bar_time)
//@variable A line connecting the current `close` to the lowest yearly price estimate.
lowLine = line.new(time, close, YTD, syminfo.target_price_low, color = color.red, xloc = xloc.bar_time)
//@variable A line connecting the current `close` to the median yearly price estimate.
medianLine = line.new(time, close, YTD, syminfo.target_price_median, color = color.gray, xloc = xloc.bar_time)
//@variable A line connecting the current `close` to the average yearly price estimate.
averageLine = line.new(time, close, YTD, syminfo.target_price_average, color = color.orange, xloc = xloc.bar_time)
// Fill the space between targets
linefill.new(lowLine, medianLine, color.new(color.red, 90))
linefill.new(medianLine, highLine, color.new(color.green, 90))
// Create a label displaying the total number of analyst estimates.
string estimatesText = str.format("Number of estimates: {0}", syminfo.target_price_estimates)
label.new(bar_index, close, estimatesText, textcolor = color.white, size = size.large)
//@version=6
indicator("syminfo target_price")
if barstate.islastconfirmedhistory
//@variable The time value one year from the date of the last analyst recommendations.
int YTD = syminfo.target_price_date + timeframe.in_seconds("12M") * 1000
//@variable A line connecting the current `close` to the highest yearly price estimate.
highLine = line.new(time, close, YTD, syminfo.target_price_high, color = color.green, xloc = xloc.bar_time)
//@variable A line connecting the current `close` to the lowest yearly price estimate.
lowLine = line.new(time, close, YTD, syminfo.target_price_low, color = color.red, xloc = xloc.bar_time)
//@variable A line connecting the current `close` to the median yearly price estimate.
medianLine = line.new(time, close, YTD, syminfo.target_price_median, color = color.gray, xloc = xloc.bar_time)
//@variable A line connecting the current `close` to the average yearly price estimate.
averageLine = line.new(time, close, YTD, syminfo.target_price_average, color = color.orange, xloc = xloc.bar_time)
// Fill the space between targets
linefill.new(lowLine, medianLine, color.new(color.red, 90))
linefill.new(medianLine, highLine, color.new(color.green, 90))
// Create a label displaying the total number of analyst estimates.
string estimatesText = str.format("Number of estimates: {0}", syminfo.target_price_estimates)
label.new(bar_index, close, estimatesText, textcolor = color.white, size = size.large)
//@version=6
indicator("syminfo target_price")
if barstate.islastconfirmedhistory
//@variable The time value one year from the date of the last analyst recommendations.
int YTD = syminfo.target_price_date + timeframe.in_seconds("12M") * 1000
//@variable A line connecting the current `close` to the highest yearly price estimate.
highLine = line.new(time, close, YTD, syminfo.target_price_high, color = color.green, xloc = xloc.bar_time)
//@variable A line connecting the current `close` to the lowest yearly price estimate.
lowLine = line.new(time, close, YTD, syminfo.target_price_low, color = color.red, xloc = xloc.bar_time)
//@variable A line connecting the current `close` to the median yearly price estimate.
medianLine = line.new(time, close, YTD, syminfo.target_price_median, color = color.gray, xloc = xloc.bar_time)
//@variable A line connecting the current `close` to the average yearly price estimate.
averageLine = line.new(time, close, YTD, syminfo.target_price_average, color = color.orange, xloc = xloc.bar_time)
// Fill the space between targets
linefill.new(lowLine, medianLine, color.new(color.red, 90))
linefill.new(medianLine, highLine, color.new(color.green, 90))
// Create a label displaying the total number of analyst estimates.
string estimatesText = str.format("Number of estimates: {0}", syminfo.target_price_estimates)
label.new(bar_index, close, estimatesText, textcolor = color.white, size = size.large)
//@version=6
indicator("syminfo target_price")
if barstate.islastconfirmedhistory
//@variable The time value one year from the date of the last analyst recommendations.
int YTD = syminfo.target_price_date + timeframe.in_seconds("12M") * 1000
//@variable A line connecting the current `close` to the highest yearly price estimate.
highLine = line.new(time, close, YTD, syminfo.target_price_high, color = color.green, xloc = xloc.bar_time)
//@variable A line connecting the current `close` to the lowest yearly price estimate.
lowLine = line.new(time, close, YTD, syminfo.target_price_low, color = color.red, xloc = xloc.bar_time)
//@variable A line connecting the current `close` to the median yearly price estimate.
medianLine = line.new(time, close, YTD, syminfo.target_price_median, color = color.gray, xloc = xloc.bar_time)
//@variable A line connecting the current `close` to the average yearly price estimate.
averageLine = line.new(time, close, YTD, syminfo.target_price_average, color = color.orange, xloc = xloc.bar_time)
// Fill the space between targets
linefill.new(lowLine, medianLine, color.new(color.red, 90))
linefill.new(medianLine, highLine, color.new(color.green, 90))
// Create a label displaying the total number of analyst estimates.
string estimatesText = str.format("Number of estimates: {0}", syminfo.target_price_estimates)
label.new(bar_index, close, estimatesText, textcolor = color.white, size = size.large)
//@version=6
indicator("syminfo target_price")
if barstate.islastconfirmedhistory
//@variable The time value one year from the date of the last analyst recommendations.
int YTD = syminfo.target_price_date + timeframe.in_seconds("12M") * 1000
//@variable A line connecting the current `close` to the highest yearly price estimate.
highLine = line.new(time, close, YTD, syminfo.target_price_high, color = color.green, xloc = xloc.bar_time)
//@variable A line connecting the current `close` to the lowest yearly price estimate.
lowLine = line.new(time, close, YTD, syminfo.target_price_low, color = color.red, xloc = xloc.bar_time)
//@variable A line connecting the current `close` to the median yearly price estimate.
medianLine = line.new(time, close, YTD, syminfo.target_price_median, color = color.gray, xloc = xloc.bar_time)
//@variable A line connecting the current `close` to the average yearly price estimate.
averageLine = line.new(time, close, YTD, syminfo.target_price_average, color = color.orange, xloc = xloc.bar_time)
// Fill the space between targets
linefill.new(lowLine, medianLine, color.new(color.red, 90))
linefill.new(medianLine, highLine, color.new(color.green, 90))
// Create a label displaying the total number of analyst estimates.
string estimatesText = str.format("Number of estimates: {0}", syminfo.target_price_estimates)
label.new(bar_index, close, estimatesText, textcolor = color.white, size = size.large)
//@version=6
indicator("syminfo target_price")
if barstate.islastconfirmedhistory
//@variable The time value one year from the date of the last analyst recommendations.
int YTD = syminfo.target_price_date + timeframe.in_seconds("12M") * 1000
//@variable A line connecting the current `close` to the highest yearly price estimate.
highLine = line.new(time, close, YTD, syminfo.target_price_high, color = color.green, xloc = xloc.bar_time)
//@variable A line connecting the current `close` to the lowest yearly price estimate.
lowLine = line.new(time, close, YTD, syminfo.target_price_low, color = color.red, xloc = xloc.bar_time)
//@variable A line connecting the current `close` to the median yearly price estimate.
medianLine = line.new(time, close, YTD, syminfo.target_price_median, color = color.gray, xloc = xloc.bar_time)
//@variable A line connecting the current `close` to the average yearly price estimate.
averageLine = line.new(time, close, YTD, syminfo.target_price_average, color = color.orange, xloc = xloc.bar_time)
// Fill the space between targets
linefill.new(lowLine, medianLine, color.new(color.red, 90))
linefill.new(medianLine, highLine, color.new(color.green, 90))
// Create a label displaying the total number of analyst estimates.
string estimatesText = str.format("Number of estimates: {0}", syminfo.target_price_estimates)
label.new(bar_index, close, estimatesText, textcolor = color.white, size = size.large)
expression argument of a request.*() function call. Otherwise, it represents the chart's ticker ID. The value contains an exchange prefix and a symbol name, separated by a colon (e.g., "NASDAQ:AAPL"). It can also include information about data modifications such as dividend adjustment, non-standard chart type, currency conversion, etc.//@version=6
indicator("Intraday Intensity Index")
plot(ta.iii, color=color.yellow)
// the same on pine
f_iii() =>
(2 * close - high - low) / ((high - low) * volume)
plot(f_iii())
//@version=6
indicator("Negative Volume Index")
plot(ta.nvi, color=color.yellow)
// the same on pine
f_nvi() =>
float ta_nvi = 1.0
float prevNvi = (nz(ta_nvi[1], 0.0) == 0.0) ? 1.0 : ta_nvi[1]
if nz(close, 0.0) == 0.0 or nz(close[1], 0.0) == 0.0
ta_nvi := prevNvi
else
ta_nvi := (volume < nz(volume[1], 0.0)) ? prevNvi + ((close - close[1]) / close[1]) * prevNvi : prevNvi
result = ta_nvi
plot(f_nvi())
//@version=6
indicator("On Balance Volume")
plot(ta.obv, color=color.yellow)
// the same on pine
f_obv() =>
ta.cum(math.sign(ta.change(close)) * volume)
plot(f_obv())
//@version=6
indicator("Positive Volume Index")
plot(ta.pvi, color=color.yellow)
// the same on pine
f_pvi() =>
float ta_pvi = 1.0
float prevPvi = (nz(ta_pvi[1], 0.0) == 0.0) ? 1.0 : ta_pvi[1]
if nz(close, 0.0) == 0.0 or nz(close[1], 0.0) == 0.0
ta_pvi := prevPvi
else
ta_pvi := (volume > nz(volume[1], 0.0)) ? prevPvi + ((close - close[1]) / close[1]) * prevPvi : prevPvi
result = ta_pvi
plot(f_pvi())
//@version=6
indicator("Price-Volume Trend")
plot(ta.pvt, color=color.yellow)
// the same on pine
f_pvt() =>
ta.cum((ta.change(close) / close[1]) * volume)
plot(f_pvt())
//@version=6
indicator("Williams Accumulation/Distribution")
plot(ta.wad, color=color.yellow)
// the same on pine
f_wad() =>
trueHigh = math.max(high, close[1])
trueLow = math.min(low, close[1])
mom = ta.change(close)
gain = (mom > 0) ? close - trueLow : (mom < 0) ? close - trueHigh : 0
ta.cum(gain)
plot(f_wad())
//@version=6
indicator("Williams Variable Accumulation/Distribution")
plot(ta.wvad, color=color.yellow)
// the same on pine
f_wvad() =>
(close - open) / (high - low) * volume
plot(f_wvad())
//@version=6
indicator("table.all")
//delete all tables
table.new(position = position.top_right, columns = 2, rows = 1, bgcolor = color.yellow, border_width = 1)
a_allTables = table.all
if array.size(a_allTables) > 0
for i = 0 to array.size(a_allTables) - 1
table.delete(array.get(a_allTables, i))
dayofmonth(time) can be lower by 1 than the date of the trading day, because the bar for the current day actually opens one day prior.time, which would return the timestamp for Sunday at 17:00 for the Monday daily bar, time_tradingday will return the timestamp for Monday, 00:00 UTC.time_tradingday returns the trading day of the last day inside the bar (e.g. on 1W, it will return the last trading day of the week).timeframe value in its declaration statement, this variable holds that value. Otherwise, its value represents the chart's timeframe. Unlike timeframe.period, this variable's value does not change when used in the expression argument of a request.*() function call.expression argument of a request.*() function call. Otherwise, its value represents the script's main timeframe (timeframe.main_period), which equals either the timeframe argument of the indicator declaration statement or the chart's timeframe.freq parameter of the alert() function.freq parameter of the alert() function.freq parameter of the alert() function.backadjustment parameter in ticker.new and ticker.modify functions.backadjustment parameter in ticker.new and ticker.modify functions.backadjustment parameter in ticker.new and ticker.modify functions.display parameter of plot*() and input*() functions. plot*() functions using this will not display their plotted values anywhere. However, alert template messages and fill functions can still use the values, and they will appear in exported chart data. input*() functions using this constant will only display their values within the script's settings.display parameter of plot*() and input*() functions. Displays plotted or input values in the status line next to the script's name on the chart if the chart's settings allow it.plot*() call uses this format option, the function's precision parameter will not affect the result.style parameter in the plot function.style parameter in the plot function. Similar to plot.style_area, except the gaps in the data are not filled.style parameter in the plot function.style parameter in the plot function.style parameter in the plot function.style parameter in the plot function.style parameter in the plot function.style parameter in the plot function. Similar to plot.style_line, except the gaps in the data are not filled.style parameter in the plot function.style parameter in the plot function. Similar to plot.style_stepline, except the data changes are also marked with the Diamond shapes.style parameter in the plot function.settlement_as_close parameter in ticker.new and ticker.modify functions.settlement_as_close parameter in ticker.new and ticker.modify functions.settlement_as_close parameter in ticker.new and ticker.modify functions.default_qty_type parameter in the strategy declaration statement. It is only relevant when no value is used for the ‘qty’ parameter in strategy.entry or strategy.order function calls. It specifies that an amount of cash in the strategy.account_currency will be used to enter trades.//@version=6
strategy("strategy.cash", overlay = true, default_qty_value = 50, default_qty_type = strategy.cash, initial_capital = 1000000)
if bar_index == 0
// As ‘qty’ is not defined, the previously defined values for the `default_qty_type` and `default_qty_value` parameters are used to enter trades, namely 50 units of cash in the currency of `strategy.account_currency`.
// `qty` is calculated as (default_qty_value)/(close price). If current price is $5, then qty = 50/5 = 10.
strategy.entry("EN", strategy.long)
if bar_index == 2
strategy.close("EN")
default_qty_type parameter in the strategy declaration statement. It is only relevant when no value is used for the ‘qty’ parameter in strategy.entry or strategy.order function calls. It specifies that a number of contracts/shares/lots will be used to enter trades.//@version=6
strategy("strategy.fixed", overlay = true, default_qty_value = 50, default_qty_type = strategy.fixed, initial_capital = 1000000)
if bar_index == 0
// As ‘qty’ is not defined, the previously defined values for the `default_qty_type` and `default_qty_value` parameters are used to enter trades, namely 50 contracts.
// qty = 50
strategy.entry("EN", strategy.long)
if bar_index == 2
strategy.close("EN")
direction parameter of the strategy.entry and strategy.order commands. It specifies that the command creates a buy order.oca_type parameter of the strategy.entry and strategy.order commands. It specifies that the strategy cancels the unfilled order when another order with the same oca_name and oca_type executes.oca_* arguments, the strategy cannot fully or partially cancel either one.oca_type parameter of the strategy.entry and strategy.order commands. It specifies that the order executes independently of all other orders, including those with the same oca_name.oca_type parameter of the strategy.entry and strategy.order commands. It specifies that when another order with the same oca_name and oca_type executes, the strategy reduces the unfilled order by that order's size. If the unfilled order's size reaches 0 after reduction, it is the same as canceling the order entirely.oca_* arguments, the strategy cannot fully or partially cancel either one.default_qty_type parameter in the strategy declaration statement. It is only relevant when no value is used for the ‘qty’ parameter in strategy.entry or strategy.order function calls. It specifies that a percentage (0-100) of equity will be used to enter trades.//@version=6
strategy("strategy.percent_of_equity", overlay = false, default_qty_value = 100, default_qty_type = strategy.percent_of_equity, initial_capital = 1000000)
// As ‘qty’ is not defined, the previously defined values for the `default_qty_type` and `default_qty_value` parameters are used to enter trades, namely 100% of available equity.
if bar_index == 0
strategy.entry("EN", strategy.long)
if bar_index == 2
strategy.close("EN")
plot(strategy.equity)
// The ‘qty’ parameter is set to 10. Entering position with fixed size of 10 contracts and entry market price = (10 * close).
if bar_index == 4
strategy.entry("EN", strategy.long, qty = 10)
if bar_index == 6
strategy.close("EN")
direction parameter of the strategy.entry and strategy.order commands. It specifies that the command creates a sell order.text_formatting parameter of the label.new(), box.new(), table.cell(), and *set_text_formatting() functions. Makes the text bold.text_formatting parameter of the label.new(), box.new(), table.cell(), and *set_text_formatting() functions. Italicizes the text.text_formatting parameter of the label.new(), box.new(), table.cell(), and *set_text_formatting() functions. Signifies no special text formatting.xloc = xloc.bar_index, the drawing object treats each x-coordinate as a bar_index value.xloc = xloc.bar_time, the drawing object treats each x-coordinate as a UNIX timestamp, expressed in milliseconds.alert(message, freq) → void
//@version=6
indicator("`alert()` example", "", true)
ma = ta.sma(close, 14)
xUp = ta.crossover(close, ma)
if xUp
// Trigger the alert the first time a cross occurs during the real-time bar.
alert("Price (" + str.tostring(close) + ") crossed over MA (" + str.tostring(ma) + ").", alert.freq_once_per_bar)
plot(ma)
plotchar(xUp, "xUp", "▲", location.top, size = size.tiny)
alert() function does not display information on the chart.alert() calls are allowed in local scopes, including the scopes of exported library functions.alert() calls.alertcondition(condition, title, message) → void
//@version=6
indicator("alertcondition", overlay=true)
alertcondition(close >= open, title='Alert on Green Bar', message='Green Bar!')
array.abs(id) → array<float>
array.abs(id) → array<int>
array.avg(id) → series float
array.avg(id) → series int
//@version=6
indicator("array.avg example")
a = array.new_float(0)
for i = 0 to 9
array.push(a, close[i])
plot(array.avg(a))
array.binary_search(id, val) → series int
//@version=6
indicator("array.binary_search")
a = array.from(5, -2, 0, 9, 1)
array.sort(a) // [-2, 0, 1, 5, 9]
position = array.binary_search(a, 0) // 1
plot(position)
array.binary_search_leftmost(id, val) → series int
//@version=6
indicator("array.binary_search_leftmost")
a = array.from(5, -2, 0, 9, 1)
array.sort(a) // [-2, 0, 1, 5, 9]
position = array.binary_search_leftmost(a, 3) // 2
plot(position)
//@version=6
indicator("array.binary_search_leftmost, repetitive elements")
a = array.from(4, 5, 5, 5)
// Returns the index of the first instance.
position = array.binary_search_leftmost(a, 5)
plot(position) // Plots 1
array.binary_search_rightmost(id, val) → series int
//@version=6
indicator("array.binary_search_rightmost")
a = array.from(5, -2, 0, 9, 1)
array.sort(a) // [-2, 0, 1, 5, 9]
position = array.binary_search_rightmost(a, 3) // 3
plot(position)
//@version=6
indicator("array.binary_search_rightmost, repetitive elements")
a = array.from(4, 5, 5, 5)
// Returns the index of the last instance.
position = array.binary_search_rightmost(a, 5)
plot(position) // Plots 3
array.clear(id) → void
//@version=6
indicator("array.clear example")
a = array.new_float(5,high)
array.clear(a)
array.push(a, close)
plot(array.get(a,0))
plot(array.size(a))
array.concat(id1, id2) → array<type>
//@version=6
indicator("array.concat example")
a = array.new_float(0,0)
b = array.new_float(0,0)
for i = 0 to 4
array.push(a, high[i])
array.push(b, low[i])
c = array.concat(a,b)
plot(array.size(a))
plot(array.size(b))
plot(array.size(c))
array.copy(id) → array<type>
//@version=6
indicator("array.copy example")
length = 5
a = array.new_float(length, close)
b = array.copy(a)
a := array.new_float(length, open)
plot(array.sum(a) / length)
plot(array.sum(b) / length)
array.covariance(id1, id2, biased) → series float
//@version=6
indicator("array.covariance example")
a = array.new_float(0)
b = array.new_float(0)
for i = 0 to 9
array.push(a, close[i])
array.push(b, open[i])
plot(array.covariance(a, b))
biased is true, function will calculate using a biased estimate of the entire population, if false - unbiased estimate of a sample.array.fill(id, value, index_from, index_to) → void
//@version=6
indicator("array.fill example")
a = array.new_float(10)
array.fill(a, close)
plot(array.sum(a))
array.first(id) → series <type>
//@version=6
indicator("array.first example")
arr = array.new_int(3, 10)
plot(array.first(arr))
array.from(arg0, arg1, ...) → array<type>
array.from(arg0, arg1, ...) → array<series enum>
array.from(arg0, arg1, ...) → array<label>
array.from(arg0, arg1, ...) → array<line>
array.from(arg0, arg1, ...) → array<box>
array.from(arg0, arg1, ...) → array<table>
array.from(arg0, arg1, ...) → array<linefill>
array.from(arg0, arg1, ...) → array<string>
array.from(arg0, arg1, ...) → array<color>
array.from(arg0, arg1, ...) → array<int>
array.from(arg0, arg1, ...) → array<float>
array.from(arg0, arg1, ...) → array<bool>
//@version=6
indicator("array.from_example", overlay = false)
arr = array.from("Hello", "World!") // arr (array<string>) will contain 2 elements: {Hello}, {World!}.
plot(close)
array.get(id, index) → series <type>
//@version=6
indicator("array.get example")
a = array.new_float(0)
for i = 0 to 9
array.push(a, close[i] - open[i])
plot(array.get(a, 9))
array.size() - 1. If the index is negative, the function counts backwards from the end of the array to the beginning. In this case, the index of the last element is -1, and the index of the first element is negative array.size(). For example, for an array that contains three elements, all of the following are valid arguments for the index parameter: 0, 1, 2, -1, -2, -3.array.includes(id, value) → series bool
//@version=6
indicator("array.includes example")
a = array.new_float(5,high)
p = close
if array.includes(a, high)
p := open
plot(p)
array.indexof(id, value) → series int
//@version=6
indicator("array.indexof example")
a = array.new_float(5,high)
index = array.indexof(a, high)
plot(index)
array.insert(id, index, value) → void
//@version=6
indicator("array.insert example")
a = array.new_float(5, close)
array.insert(a, 0, open)
plot(array.get(a, 5))
array.size() - 1. If the index is negative, the function counts backwards from the end of the array to the beginning. In this case, the index of the last element is -1, and the index of the first element is negative array.size(). For example, for an array that contains three elements, all of the following are valid arguments for the index parameter: 0, 1, 2, -1, -2, -3.array.join(id, separator) → series string
//@version=6
indicator("array.join example")
a = array.new_float(5, 5)
label.new(bar_index, close, array.join(a, ","))
array.last(id) → series <type>
//@version=6
indicator("array.last example")
arr = array.new_int(3, 10)
plot(array.last(arr))
array.lastindexof(id, value) → series int
//@version=6
indicator("array.lastindexof example")
a = array.new_float(5,high)
index = array.lastindexof(a, high)
plot(index)
array.max(id, nth) → series float
array.max(id, nth) → series int
//@version=6
indicator("array.max")
a = array.from(5, -2, 0, 9, 1)
thirdHighest = array.max(a, 2) // 1
plot(thirdHighest)
array.median(id) → series float
array.median(id) → series int
//@version=6
indicator("array.median example")
a = array.new_float(0)
for i = 0 to 9
array.push(a, close[i])
plot(array.median(a))
array.min(id, nth) → series float
array.min(id, nth) → series int
//@version=6
indicator("array.min")
a = array.from(5, -2, 0, 9, 1)
secondLowest = array.min(a, 1) // 0
plot(secondLowest)
array.mode(id) → series float
array.mode(id) → series int
//@version=6
indicator("array.mode example")
a = array.new_float(0)
for i = 0 to 9
array.push(a, close[i])
plot(array.mode(a))
id array. If none exists, returns the smallest value instead.array.new_bool(size, initial_value) → array<bool>
//@version=6
indicator("array.new_bool example")
length = 5
a = array.new_bool(length, close > open)
plot(array.get(a, 0) ? close : open)
array.new_box(size, initial_value) → array<box>
//@version=6
indicator("array.new_box example")
boxes = array.new_box()
array.push(boxes, box.new(time, close, time+2, low, xloc=xloc.bar_time))
plot(1)
array.new_color(size, initial_value) → array<color>
//@version=6
indicator("array.new_color example")
length = 5
a = array.new_color(length, color.red)
plot(close, color = array.get(a, 0))
array.new_float(size, initial_value) → array<float>
//@version=6
indicator("array.new_float example")
length = 5
a = array.new_float(length, close)
plot(array.sum(a) / length)
array.new_int(size, initial_value) → array<int>
//@version=6
indicator("array.new_int example")
length = 5
a = array.new_int(length, int(close))
plot(array.sum(a) / length)
array.new_label(size, initial_value) → array<label>
//@version=6
indicator("array.new_label example", overlay = true, max_labels_count = 500)
//@variable The number of labels to show on the chart.
int labelCount = input.int(50, "Labels to show", 1, 500)
//@variable An array of `label` objects.
var array<label> labelArray = array.new_label()
//@variable A `chart.point` for the new label.
labelPoint = chart.point.from_index(bar_index, close)
//@variable The text in the new label.
string labelText = na
//@variable The color of the new label.
color labelColor = na
//@variable The style of the new label.
string labelStyle = na
// Set the label attributes for rising bars.
if close > open
labelText := "Rising"
labelColor := color.green
labelStyle := label.style_label_down
// Set the label attributes for falling bars.
else if close < open
labelText := "Falling"
labelColor := color.red
labelStyle := label.style_label_up
// Add a new label to the `labelArray` when the chart bar closed at a new value.
if close != open
labelArray.push(label.new(labelPoint, labelText, color = labelColor, style = labelStyle))
// Remove the first element and delete its label when the size of the `labelArray` exceeds the `labelCount`.
if labelArray.size() > labelCount
label.delete(labelArray.shift())
array.new_line(size, initial_value) → array<line>
//@version=6
indicator("array.new_line example")
// draw last 15 lines
var a = array.new_line()
array.push(a, line.new(bar_index - 1, close[1], bar_index, close))
if array.size(a) > 15
ln = array.shift(a)
line.delete(ln)
array.new_linefill(size, initial_value) → array<linefill>
array.new_string(size, initial_value) → array<string>
//@version=6
indicator("array.new_string example")
length = 5
a = array.new_string(length, "text")
label.new(bar_index, close, array.get(a, 0))
array.new_table(size, initial_value) → array<table>
//@version=6
indicator("table array")
tables = array.new_table()
array.push(tables, table.new(position = position.top_left, rows = 1, columns = 2, bgcolor = color.yellow, border_width=1))
plot(1)
array.new<type>(size, initial_value) → array<type>
//@version=6
indicator("array.new<string> example")
a = array.new<string>(1, "Hello, World!")
label.new(bar_index, close, array.get(a, 0))
//@version=6
indicator("array.new<color> example")
a = array.new<color>()
array.push(a, color.red)
array.push(a, color.green)
plot(close, color = array.get(a, close > open ? 1 : 0))
//@version=6
indicator("array.new<float> example")
length = 5
var a = array.new<float>(length, close)
if array.size(a) == length
array.remove(a, 0)
array.push(a, close)
plot(array.sum(a) / length, "SMA")
//@version=6
indicator("array.new<line> example")
// draw last 15 lines
var a = array.new<line>()
array.push(a, line.new(bar_index - 1, close[1], bar_index, close))
if array.size(a) > 15
ln = array.shift(a)
line.delete(ln)
array.percentile_linear_interpolation(id, percentage) → series float
array.percentile_linear_interpolation(id, percentage) → series int
array.percentile_nearest_rank(id, percentage) → series float
array.percentile_nearest_rank(id, percentage) → series int
index.array.percentrank(id, index) → series float
array.percentrank(id, index) → series int
array.pop(id) → series <type>
//@version=6
indicator("array.pop example")
a = array.new_float(5,high)
removedEl = array.pop(a)
plot(array.size(a))
plot(removedEl)
array.push(id, value) → void
//@version=6
indicator("array.push example")
a = array.new_float(5, 0)
array.push(a, open)
plot(array.get(a, 5))
array.range(id) → series float
array.range(id) → series int
//@version=6
indicator("array.range example")
a = array.new_float(0)
for i = 0 to 9
array.push(a, close[i])
plot(array.range(a))
array.remove(id, index) → series <type>
//@version=6
indicator("array.remove example")
a = array.new_float(5,high)
removedEl = array.remove(a, 0)
plot(array.size(a))
plot(removedEl)
array.size() - 1. If the index is negative, the function counts backwards from the end of the array to the beginning. In this case, the index of the last element is -1, and the index of the first element is negative array.size(). For example, for an array that contains three elements, all of the following are valid arguments for the index parameter: 0, 1, 2, -1, -2, -3.array.reverse(id) → void
//@version=6
indicator("array.reverse example")
a = array.new_float(0)
for i = 0 to 9
array.push(a, close[i])
plot(array.get(a, 0))
array.reverse(a)
plot(array.get(a, 0))
array.set(id, index, value) → void
//@version=6
indicator("array.set example")
a = array.new_float(10)
for i = 0 to 9
array.set(a, i, close[i])
plot(array.sum(a) / 10)
array.size() - 1. If the index is negative, the function counts backwards from the end of the array to the beginning. In this case, the index of the last element is -1, and the index of the first element is negative array.size(). For example, for an array that contains three elements, all of the following are valid arguments for the index parameter: 0, 1, 2, -1, -2, -3.array.shift(id) → series <type>
//@version=6
indicator("array.shift example")
a = array.new_float(5,high)
removedEl = array.shift(a)
plot(array.size(a))
plot(removedEl)
array.size(id) → series int
//@version=6
indicator("array.size example")
a = array.new_float(0)
for i = 0 to 9
array.push(a, close[i])
// note that changes in slice also modify original array
slice = array.slice(a, 0, 5)
array.push(slice, open)
// size was changed in slice and in original array
plot(array.size(a))
plot(array.size(slice))
array.slice(id, index_from, index_to) → array<type>
//@version=6
indicator("array.slice example")
a = array.new_float(0)
for i = 0 to 9
array.push(a, close[i])
// take elements from 0 to 4
// *note that changes in slice also modify original array
slice = array.slice(a, 0, 5)
plot(array.sum(a) / 10)
plot(array.sum(slice) / 5)
array.sort(id, order) → void
//@version=6
indicator("array.sort example")
a = array.new_float(0,0)
for i = 0 to 5
array.push(a, high[i])
array.sort(a, order.descending)
if barstate.islast
label.new(bar_index, close, str.tostring(a))
array.sort_indices(id, order) → array<int>
//@version=6
indicator("array.sort_indices")
a = array.from(5, -2, 0, 9, 1)
sortedIndices = array.sort_indices(a) // [1, 2, 4, 0, 3]
indexOfSmallestValue = array.get(sortedIndices, 0) // 1
smallestValue = array.get(a, indexOfSmallestValue) // -2
plot(smallestValue)
array.standardize(id) → array<float>
array.standardize(id) → array<int>
//@version=6
indicator("array.standardize example")
a = array.new_float(0)
for i = 0 to 9
array.push(a, close[i])
b = array.standardize(a)
plot(array.min(b))
plot(array.max(b))
array.stdev(id, biased) → series float
array.stdev(id, biased) → series int
//@version=6
indicator("array.stdev example")
a = array.new_float(0)
for i = 0 to 9
array.push(a, close[i])
plot(array.stdev(a))
biased is true, function will calculate using a biased estimate of the entire population, if false - unbiased estimate of a sample.array.sum(id) → series float
array.sum(id) → series int
//@version=6
indicator("array.sum example")
a = array.new_float(0)
for i = 0 to 9
array.push(a, close[i])
plot(array.sum(a))
array.unshift(id, value) → void
//@version=6
indicator("array.unshift example")
a = array.new_float(5, 0)
array.unshift(a, open)
plot(array.get(a, 0))
array.variance(id, biased) → series float
array.variance(id, biased) → series int
//@version=6
indicator("array.variance example")
a = array.new_float(0)
for i = 0 to 9
array.push(a, close[i])
plot(array.variance(a))
biased is true, function will calculate using a biased estimate of the entire population, if false - unbiased estimate of a sample.barcolor(color, offset, editable, show_last, title, display) → void
//@version=6
indicator("barcolor example", overlay=true)
barcolor(close < open ? color.black : color.white)
bgcolor(color, offset, editable, show_last, title, display, force_overlay) → void
//@version=6
indicator("bgcolor example", overlay=true)
bgcolor(close < open ? color.new(color.red,70) : color.new(color.green, 70))
x value to a bool value. Returns false if x is na, false, or an int/float value equal to 0. Returns true for all other possible values.bool(x) → const bool
bool(x) → input bool
bool(x) → simple bool
bool(x) → series bool
box.copy(id) → series box
//@version=6
indicator('Last 50 bars price ranges', overlay = true)
LOOKBACK = 50
highest = ta.highest(LOOKBACK)
lowest = ta.lowest(LOOKBACK)
if barstate.islastconfirmedhistory
var BoxLast = box.new(bar_index[LOOKBACK], highest, bar_index, lowest, bgcolor = color.new(color.green, 80))
var BoxPrev = box.copy(BoxLast)
box.set_lefttop(BoxPrev, bar_index[LOOKBACK * 2], highest[50])
box.set_rightbottom(BoxPrev, bar_index[LOOKBACK], lowest[50])
box.set_bgcolor(BoxPrev, color.new(color.red, 80))
box.delete(id) → void
box.get_bottom(id) → series float
box.get_left(id) → series int
box.get_right(id) → series int
box.get_top(id) → series float
box.new(top_left, bottom_right, border_color, border_width, border_style, extend, xloc, bgcolor, text, text_size, text_color, text_halign, text_valign, text_wrap, text_font_family, force_overlay, text_formatting) → series box
box.new(left, top, right, bottom, border_color, border_width, border_style, extend, xloc, bgcolor, text, text_size, text_color, text_halign, text_valign, text_wrap, text_font_family, force_overlay, text_formatting) → series box
size.* built-in constant strings. The constant strings and their equivalent integer values are: size.auto (0), size.tiny (8), size.small (10), size.normal (14), size.large (20), size.huge (36). The default value is size.auto or 0.text_size is 0 or text.wrap_auto, this setting has no effect. The default value is text.wrap_none. Possible values: text.wrap_none, text.wrap_auto.text.format_bold + text.format_italic will make the text both bold and italicized. Possible values: text.format_none, text.format_bold, text.format_italic. Optional. The default is text.format_none.//@version=6
indicator("box.new")
var b = box.new(time, open, time + 60 * 60 * 24, close, xloc=xloc.bar_time, border_style=line.style_dashed)
box.set_lefttop(b, time, 100)
box.set_rightbottom(b, time + 60 * 60 * 24, 500)
box.set_bgcolor(b, color.green)
box.set_bgcolor(id, color) → void
box.set_border_color(id, color) → void
box.set_border_style(id, style) → void
box.set_border_width(id, width) → void
box.set_bottom(id, bottom) → void
id box to point.box.set_bottom_right_point(id, point) → void
box.set_extend(id, extend) → void
box.set_left(id, left) → void
box.set_lefttop(id, left, top) → void
box.set_right(id, right) → void
box.set_rightbottom(id, right, bottom) → void
box.set_text(id, text) → void
box.set_text_color(id, text_color) → void
box.set_text_font_family(id, text_font_family) → void
//@version=6
indicator("Example of setting the box font")
if barstate.islastconfirmedhistory
b = box.new(bar_index, open-ta.tr, bar_index-50, open-ta.tr*5, text="monospace")
box.set_text_font_family(b, font.family_monospace)
box.set_text_formatting(id, text_formatting) → void
text.format_bold + text.format_italic will make the text both bold and italicized. Possible values: text.format_none, text.format_bold, text.format_italic.box.set_text_halign(id, text_halign) → void
box.set_text_size(id, text_size) → void
size.* built-in constant strings. The constant strings and their equivalent integer values are: size.auto (0), size.tiny (8), size.small (10), size.normal (14), size.large (20), size.huge (36).box.set_text_valign(id, text_valign) → void
box.set_text_wrap(id, text_wrap) → void
text_size is 0 or text.wrap_auto, this setting has no effect. Possible values: text.wrap_none, text.wrap_auto.box.set_top(id, top) → void
id box to point.box.set_top_left_point(id, point) → void
xloc property.box.set_xloc(id, left, right, xloc) → void
left and right arguments as bar indices or timestamps. Possible values: xloc.bar_index and xloc.bar_time. If the value is xloc.bar_index, the arguments represent bar indices. If xloc.bar_time, the arguments represent UNIX timestamps.id.chart.point.copy(id) → chart.point
chart.point.from_index(index, price) → chart.point
time field values of chart.point instances returned from this function will be na, meaning drawing objects with xloc values set to xloc.bar_time will not work with them.chart.point.from_time(time, price) → chart.point
index field values of chart.point instances returned from this function will be na, meaning drawing objects with xloc values set to xloc.bar_index will not work with them.chart.point.new(time, index, price) → chart.point
time or index field as an x-coordinate depends on the xloc type used in the function call that returned the drawing.time and index values refer to the same bar.price as the y-coordinatechart.point.now(price) → chart.point
index and time fields on the bar it executed on, making it suitable for use with drawing objects of any xloc type.color(x) → const color
color(x) → input color
color(x) → simple color
color(x) → series color
color.b(color) → const float
color.b(color) → input float
color.b(color) → simple float
color.b(color) → series float
//@version=6
indicator("color.b", overlay=true)
plot(color.b(color.blue))
color.from_gradient(value, bottom_value, top_value, bottom_color, top_color) → series color
//@version=6
indicator("color.from_gradient", overlay=true)
color1 = color.from_gradient(close, low, high, color.yellow, color.lime)
color2 = color.from_gradient(ta.rsi(close, 7), 0, 100, color.rgb(255, 0, 0), color.rgb(0, 255, 0, 50))
plot(close, color=color1)
plot(ta.rsi(close,7), color=color2)
color.g(color) → const float
color.g(color) → input float
color.g(color) → simple float
color.g(color) → series float
//@version=6
indicator("color.g", overlay=true)
plot(color.g(color.green))
color.new(color, transp) → const color
color.new(color, transp) → input color
color.new(color, transp) → simple color
color.new(color, transp) → series color
//@version=6
indicator("color.new", overlay=true)
plot(close, color=color.new(color.red, 50))
color.r(color) → const float
color.r(color) → input float
color.r(color) → simple float
color.r(color) → series float
//@version=6
indicator("color.r", overlay=true)
plot(color.r(color.red))
color.rgb(red, green, blue, transp) → const color
color.rgb(red, green, blue, transp) → input color
color.rgb(red, green, blue, transp) → simple color
color.rgb(red, green, blue, transp) → series color
//@version=6
indicator("color.rgb", overlay=true)
plot(close, color=color.rgb(255, 0, 0, 50))
color.t(color) → const float
color.t(color) → input float
color.t(color) → simple float
color.t(color) → series float
//@version=6
indicator("color.t", overlay=true)
plot(color.t(color.new(color.red, 50)))
dayofmonth(time, timezone) → series int
dayofweek(time, timezone) → series int
fill(hline1, hline2, color, title, editable, fillgaps, display) → void
fill(plot1, plot2, color, title, editable, show_last, fillgaps, display) → void
fill(plot1, plot2, top_value, bottom_value, top_color, bottom_color, title, display, fillgaps, editable) → void
//@version=6
indicator("Fill between hlines", overlay = false)
h1 = hline(20)
h2 = hline(10)
fill(h1, h2, color = color.new(color.blue, 90))
//@version=6
indicator("Fill between plots", overlay = true)
p1 = plot(open)
p2 = plot(close)
fill(p1, p2, color = color.new(color.green, 90))
//@version=6
indicator("Gradient Fill between hlines", overlay = false)
topVal = input.int(100)
botVal = input.int(0)
topCol = input.color(color.red)
botCol = input.color(color.blue)
topLine = hline(100, color = topCol, linestyle = hline.style_solid)
botLine = hline(0, color = botCol, linestyle = hline.style_solid)
fill(topLine, botLine, topVal, botVal, topCol, botCol)
fixnan(source) → series color
fixnan(source) → series int
fixnan(source) → series float
float(x) → const float
float(x) → input float
float(x) → simple float
float(x) → series float
hline(price, title, color, linestyle, linewidth, editable, display) → hline
//@version=6
indicator("input.hline", overlay=true)
hline(3.14, title='Pi', color=color.blue, linestyle=hline.style_dotted, linewidth=2)
// You may fill the background between any two hlines with a fill() function:
h1 = hline(20)
h2 = hline(10)
fill(h1, h2, color=color.new(color.green, 90))
hour(time, timezone) → series int
indicator(title, shorttitle, overlay, format, precision, scale, max_bars_back, timeframe, timeframe_gaps, explicit_plot_zorder, max_lines_count, max_labels_count, max_boxes_count, calc_bars_count, max_polylines_count, dynamic_requests, behind_chart) → void
shorttitle argument is used, and becomes the publication's default title when publishing the script.title argument in most chart-related windows. Optional. The default is the argument used for title.format is set to format.inherit and precision is specified, the format will instead be set to format.price. When the function's format parameter uses format.volume, the precision parameter will not affect the result, as the decimal precision rules defined by format.volume supersede other precision settings. Optional. The default is inherited from the precision of the chart's symbol.overlay = true. Optional. By default, the script uses the same scale as the chart.[] history-referencing operator. The required buffer size is automatically detected by the Pine Script® runtime. Using this parameter is only necessary when a runtime error occurs because automatic detection fails. More information on the underlying mechanics of the historical buffer can be found in our Help Center. Optional. The default is 0.timeframe is higher than the chart's. If true, a value only appears on a chart bar when the higher timeframe value becomes available, otherwise na is returned (thus a "gap" occurs). With false, what would otherwise be gaps are filled with the latest known value returned, avoiding na values. When specified, a "Wait for timeframe closes" checkbox will be included in the "Calculation" section of the script's "Settings/Inputs" tab. Optional. The default is true.plot*() functions, fill, and hline. Optional. The default is false.request.*() namespace. Dynamic request.*() calls are allowed within the local scopes of conditional structures (e.g., if), loops (e.g., for), and exported functions. Additionally, such calls allow "series" arguments for many of their parameters. Optional. The default is true. See the User Manual's Dynamic requests section for more information.//@version=6
indicator("My script", shorttitle="Script")
plot(close)
input(defval, title, tooltip, inline, group, display, active) → input color
input(defval, title, tooltip, inline, group, display, active) → input string
input(defval, title, tooltip, inline, group, display, active) → input int
input(defval, title, tooltip, inline, group, display, active) → input float
input(defval, title, inline, group, tooltip, display, active) → series float
input(defval, title, tooltip, inline, group, display, active) → input bool
close, hlc3, etc.defval: display.none for bool and color values, display.all for everything else.//@version=6
indicator("input", overlay=true)
i_switch = input(true, "On/Off")
plot(i_switch ? open : na)
i_len = input(7, "Length")
i_src = input(close, "Source")
plot(ta.sma(i_src, i_len))
i_border = input(142.50, "Price Border")
hline(i_border)
bgcolor(close > i_border ? color.green : color.red)
i_col = input(color.red, "Plot Color")
plot(close, color=i_col)
i_text = input("Hello!", "Message")
l = label.new(bar_index, high, text=i_text)
label.delete(l[1])
input.bool(defval, title, tooltip, inline, group, confirm, display, active) → input bool
//@version=6
indicator("input.bool", overlay=true)
i_switch = input.bool(true, "On/Off")
plot(i_switch ? open : na)
input.color(defval, title, tooltip, inline, group, confirm, display, active) → input color
//@version=6
indicator("input.color", overlay=true)
i_col = input.color(color.red, "Plot Color")
plot(close, color=i_col)
defval and options parameters.input.enum(defval, title, options, tooltip, inline, group, confirm, display, active) → input enum
options parameter has a specified tuple of enum fields, the tuple must include the defval.options argument limits the list to only the included fields.true, then user will be asked to confirm input value before indicator is added to chart. Default value is false.//@version=6
indicator("Session highlight", overlay = true)
//@enum Contains fields with popular timezones as titles.
//@field exch Has an empty string as the title to represent the chart timezone.
enum tz
utc = "UTC"
exch = ""
ny = "America/New_York"
chi = "America/Chicago"
lon = "Europe/London"
tok = "Asia/Tokyo"
//@variable The session string.
selectedSession = input.session("1200-1500", "Session")
//@variable The selected timezone. The input's dropdown contains the fields in the `tz` enum.
selectedTimezone = input.enum(tz.utc, "Session Timezone")
//@variable Is `true` if the current bar's time is in the specified session.
bool inSession = false
if not na(time("", selectedSession, str.tostring(selectedTimezone)))
inSession := true
// Highlight the background when `inSession` is `true`.
bgcolor(inSession ? color.new(color.green, 90) : na, title = "Active session highlight")
defval and options arguments must belong to the same enum.input.float(defval, title, options, tooltip, inline, group, confirm, display, active) → input float
input.float(defval, title, minval, maxval, step, tooltip, inline, group, confirm, display, active) → input float
options parameter, the value must be one of them.minval, maxval and step parameters cannot be used.//@version=6
indicator("input.float", overlay=true)
i_angle1 = input.float(0.5, "Sin Angle", minval=-3.14, maxval=3.14, step=0.02)
plot(math.sin(i_angle1) > 0 ? close : open, "sin", color=color.green)
i_angle2 = input.float(0, "Cos Angle", options=[-3.14, -1.57, 0, 1.57, 3.14])
plot(math.cos(i_angle2) > 0 ? close : open, "cos", color=color.red)
input.int(defval, title, options, tooltip, inline, group, confirm, display, active) → input int
input.int(defval, title, minval, maxval, step, tooltip, inline, group, confirm, display, active) → input int
options parameter, the value must be one of them.minval, maxval and step parameters cannot be used.//@version=6
indicator("input.int", overlay=true)
i_len1 = input.int(10, "Length 1", minval=5, maxval=21, step=1)
plot(ta.sma(close, i_len1))
i_len2 = input.int(10, "Length 2", options=[5, 10, 21])
plot(ta.sma(close, i_len2))
confirm = true activates the interactive input mode where a price is selected by clicking on the chart.input.price(defval, title, tooltip, inline, group, confirm, display, active) → input float
//@version=6
indicator("input.price", overlay=true)
price1 = input.price(title="Date", defval=42)
plot(price1)
price2 = input.price(54, title="Date")
plot(price2)
inline parameter.input.session(defval, title, options, tooltip, inline, group, confirm, display, active) → input string
options parameter, the value must be one of them.//@version=6
indicator("input.session", overlay=true)
i_sess = input.session("1300-1700", "Session", options=["0930-1600", "1300-1700", "1700-2100"])
t = time(timeframe.period, i_sess)
bgcolor(time == t ? color.green : na)
input.source(defval, title, tooltip, inline, group, display, active, confirm) → series float
//@version=6
indicator("input.source", overlay=true)
i_src = input.source(close, "Source")
plot(i_src)
input.string(defval, title, options, tooltip, inline, group, confirm, display, active) → input string
options parameter, the value must be one of them.//@version=6
indicator("input.string", overlay=true)
i_text = input.string("Hello!", "Message")
l = label.new(bar_index, high, i_text)
label.delete(l[1])
input.symbol(defval, title, tooltip, inline, group, confirm, display, active) → input string
//@version=6
indicator("input.symbol", overlay=true)
i_sym = input.symbol("DELL", "Symbol")
s = request.security(i_sym, 'D', close)
plot(s)
input.text_area(defval, title, tooltip, group, confirm, display, active) → input string
//@version=6
indicator("input.text_area")
i_text = input.text_area(defval = "Hello \nWorld!", title = "Message")
plot(close)
confirm = true activates the interactive input mode where a point in time is selected by clicking on the chart.input.time(defval, title, tooltip, inline, group, confirm, display, active) → input int
//@version=6
indicator("input.time", overlay=true)
i_date = input.time(timestamp("20 Jul 2021 00:00 +0300"), "Date")
l = label.new(i_date, high, "Date", xloc=xloc.bar_time)
label.delete(l[1])
inline parameter.input.timeframe(defval, title, options, tooltip, inline, group, confirm, display, active) → input string
options parameter, the value must be one of them.//@version=6
indicator("input.timeframe", overlay=true)
i_res = input.timeframe('D', "Resolution", options=['D', 'W', 'M'])
s = request.security("AAPL", i_res, close)
plot(s)
int(x) → const int
int(x) → input int
int(x) → simple int
int(x) → series int
label.copy(id) → series label
//@version=6
indicator('Last 100 bars highest/lowest', overlay = true)
LOOKBACK = 100
highest = ta.highest(LOOKBACK)
highestBars = ta.highestbars(LOOKBACK)
lowest = ta.lowest(LOOKBACK)
lowestBars = ta.lowestbars(LOOKBACK)
if barstate.islastconfirmedhistory
var labelHigh = label.new(bar_index + highestBars, highest, str.tostring(highest), color = color.green)
var labelLow = label.copy(labelHigh)
label.set_xy(labelLow, bar_index + lowestBars, lowest)
label.set_text(labelLow, str.tostring(lowest))
label.set_color(labelLow, color.red)
label.set_style(labelLow, label.style_label_up)
label.delete(id) → void
label.get_text(id) → series string
//@version=6
indicator("label.get_text")
my_label = label.new(time, open, text="Open bar text", xloc=xloc.bar_time)
a = label.get_text(my_label)
label.new(time, close, text = a + " new", xloc=xloc.bar_time)
label.get_x(id) → series int
//@version=6
indicator("label.get_x")
my_label = label.new(time, open, text="Open bar text", xloc=xloc.bar_time)
a = label.get_x(my_label)
plot(time - label.get_x(my_label)) //draws zero plot
label.get_y(id) → series float
label.new(point, text, xloc, yloc, color, style, textcolor, size, textalign, tooltip, text_font_family, force_overlay, text_formatting) → series label
label.new(x, y, text, xloc, yloc, color, style, textcolor, size, textalign, tooltip, text_font_family, force_overlay, text_formatting) → series label
size.* constants. The constants and their equivalent numeric sizes are: size.auto (0), size.tiny (~7), size.small (~10), size.normal (12), size.large (18), size.huge (24). The default value is size.normal, which represents the numeric size of 12.text.format_bold + text.format_italic will make the text both bold and italicized. Possible values: text.format_none, text.format_bold, text.format_italic. Optional. The default is text.format_none.//@version=6
indicator("label.new")
var label1 = label.new(bar_index, low, text="Hello, world!", style=label.style_circle)
label.set_x(label1, 0)
label.set_xloc(label1, time, xloc.bar_time)
label.set_color(label1, color.red)
label.set_size(label1, size.large)
label.set_color(id, color) → void
id label to point.label.set_point(id, point) → void
label.set_size(id, size) → void
size.* constants. The constants and their equivalent numeric sizes are: size.auto (0), size.tiny (~7), size.small (~10), size.normal (12), size.large (18), size.huge (24). The default value is size.normal, which represents the numeric size of 12.label.set_style(id, style) → void
label.set_text(id, text) → void
label.set_text_font_family(id, text_font_family) → void
//@version=6
indicator("Example of setting the label font")
if barstate.islastconfirmedhistory
l = label.new(bar_index, 0, "monospace", yloc=yloc.abovebar)
label.set_text_font_family(l, font.family_monospace)
label.set_text_formatting(id, text_formatting) → void
text.format_bold + text.format_italic will make the text both bold and italicized. Possible values: text.format_none, text.format_bold, text.format_italic. Optional. The default is text.format_none.label.set_textalign(id, textalign) → void
label.set_textcolor(id, textcolor) → void
label.set_tooltip(id, tooltip) → void
label.set_x(id, x) → void
label.set_xloc(id, x, xloc) → void
label.set_xy(id, x, y) → void
label.set_y(id, y) → void
label.set_yloc(id, yloc) → void
library(title, overlay, dynamic_requests) → void
request.*() namespace. Dynamic request.*() calls are allowed within the local scopes of conditional structures (e.g., if), loops (e.g., for), and exported functions. Additionally, such calls allow "series" arguments for many of their parameters. Optional. The default is true. See the User Manual's Dynamic requests section for more information.//@version=6
// @description Math library
library("num_methods", overlay = true)
// Calculate "sinh()" from the float parameter `x`
export sinh(float x) =>
(math.exp(x) - math.exp(-x)) / 2.0
plot(sinh(0))
line.copy(id) → series line
//@version=6
indicator('Last 100 bars price range', overlay = true)
LOOKBACK = 100
highest = ta.highest(LOOKBACK)
lowest = ta.lowest(LOOKBACK)
if barstate.islastconfirmedhistory
var lineTop = line.new(bar_index[LOOKBACK], highest, bar_index, highest, color = color.green)
var lineBottom = line.copy(lineTop)
line.set_y1(lineBottom, lowest)
line.set_y2(lineBottom, lowest)
line.set_color(lineBottom, color.red)
line.delete(id) → void
line.get_price(id, x) → series float
//@version=6
indicator("GetPrice", overlay=true)
var line l = na
if bar_index == 10
l := line.new(0, high[5], bar_index, high)
plot(line.get_price(l, bar_index), color=color.green)
line.get_x1(id) → series int
//@version=6
indicator("line.get_x1")
my_line = line.new(time, open, time + 60 * 60 * 24, close, xloc=xloc.bar_time)
a = line.get_x1(my_line)
plot(time - line.get_x1(my_line)) //draws zero plot
line.get_x2(id) → series int
line.get_y1(id) → series float
line.get_y2(id) → series float
line.new(first_point, second_point, xloc, extend, color, style, width, force_overlay) → series line
line.new(x1, y1, x2, y2, xloc, extend, color, style, width, force_overlay) → series line
//@version=6
indicator("line.new")
var line1 = line.new(0, low, bar_index, high, extend=extend.right)
var line2 = line.new(time, open, time + 60 * 60 * 24, close, xloc=xloc.bar_time, style=line.style_dashed)
line.set_x2(line1, 0)
line.set_xloc(line1, time, time + 60 * 60 * 24, xloc.bar_time)
line.set_color(line2, color.green)
line.set_width(line2, 5)
line.set_color(id, color) → void
line.set_extend(id, extend) → void
id line to point.line.set_first_point(id, point) → void
id line to point.line.set_second_point(id, point) → void
line.set_style(id, style) → void
line.set_width(id, width) → void
line.set_x1(id, x) → void
line.set_x2(id, x) → void
line.set_xloc(id, x1, x2, xloc) → void
line.set_xy1(id, x, y) → void
line.set_xy2(id, x, y) → void
line.set_y1(id, y) → void
line.set_y2(id, y) → void
linefill.delete(id) → void
id linefill.linefill.get_line1(id) → series line
id linefill.linefill.get_line2(id) → series line
line1 and line2 with the color specified in color.linefill.new(line1, line2, color) → series linefill
extend= parameter), the space between line extensions will also be filled.linefill.set_color(id, color) → void
log.error(message) → void
log.error(formatString, arg0, arg1, ...) → void
//@version=6
strategy("My strategy", overlay = true, process_orders_on_close = true)
bracketTickSizeInput = input.int(1000, "Stoploss/Take-Profit distance (in ticks)")
longCondition = ta.crossover(ta.sma(close, 14), ta.sma(close, 28))
if (longCondition)
limitLevel = close * 1.01
log.info("Long limit order has been placed at {0}", limitLevel)
strategy.order("My Long Entry Id", strategy.long, limit = limitLevel)
log.info("Exit orders have been placed: Take-profit at {0}, Stop-loss at {1}", close, limitLevel)
strategy.exit("Exit", "My Long Entry Id", profit = bracketTickSizeInput, loss = bracketTickSizeInput)
if strategy.opentrades > 10
log.warning("{0} positions opened in the same direction in a row. Try adjusting `bracketTickSizeInput`", strategy.opentrades)
last10Perc = strategy.initial_capital / 10 > strategy.equity
if (last10Perc and not last10Perc[1])
log.error("The strategy has lost 90% of the initial capital!")
{}. The list of additional formatting options can be found in the EXAMPLE section of the str.format article.formatString argument can contain single quote characters ('). However, one must pair all single quotes in that string to avoid unexpected formatting results.log.*() functions.log.info(message) → void
log.info(formatString, arg0, arg1, ...) → void
//@version=6
strategy("My strategy", overlay = true, process_orders_on_close = true)
bracketTickSizeInput = input.int(1000, "Stoploss/Take-Profit distance (in ticks)")
longCondition = ta.crossover(ta.sma(close, 14), ta.sma(close, 28))
if (longCondition)
limitLevel = close * 1.01
log.info("Long limit order has been placed at {0}", limitLevel)
strategy.order("My Long Entry Id", strategy.long, limit = limitLevel)
log.info("Exit orders have been placed: Take-profit at {0}, Stop-loss at {1}", close, limitLevel)
strategy.exit("Exit", "My Long Entry Id", profit = bracketTickSizeInput, loss = bracketTickSizeInput)
if strategy.opentrades > 10
log.warning("{0} positions opened in the same direction in a row. Try adjusting `bracketTickSizeInput`", strategy.opentrades)
last10Perc = strategy.initial_capital / 10 > strategy.equity
if (last10Perc and not last10Perc[1])
log.error("The strategy has lost 90% of the initial capital!")
{}. The list of additional formatting options can be found in the EXAMPLE section of the str.format article.formatString argument can contain single quote characters ('). However, one must pair all single quotes in that string to avoid unexpected formatting results.log.*() functions.log.warning(message) → void
log.warning(formatString, arg0, arg1, ...) → void
//@version=6
strategy("My strategy", overlay = true, process_orders_on_close = true)
bracketTickSizeInput = input.int(1000, "Stoploss/Take-Profit distance (in ticks)")
longCondition = ta.crossover(ta.sma(close, 14), ta.sma(close, 28))
if (longCondition)
limitLevel = close * 1.01
log.info("Long limit order has been placed at {0}", limitLevel)
strategy.order("My Long Entry Id", strategy.long, limit = limitLevel)
log.info("Exit orders have been placed: Take-profit at {0}, Stop-loss at {1}", close, limitLevel)
strategy.exit("Exit", "My Long Entry Id", profit = bracketTickSizeInput, loss = bracketTickSizeInput)
if strategy.opentrades > 10
log.warning("{0} positions opened in the same direction in a row. Try adjusting `bracketTickSizeInput`", strategy.opentrades)
last10Perc = strategy.initial_capital / 10 > strategy.equity
if (last10Perc and not last10Perc[1])
log.error("The strategy has lost 90% of the initial capital!")
{}. The list of additional formatting options can be found in the EXAMPLE section of the str.format article.formatString argument can contain single quote characters ('). However, one must pair all single quotes in that string to avoid unexpected formatting results.log.*() functions.map.clear(id) → void
//@version=6
indicator("map.clear example")
oddMap = map.new<int, bool>()
oddMap.put(1, true)
oddMap.put(2, false)
oddMap.put(3, true)
map.clear(oddMap)
plot(oddMap.size())
map.contains(id, key) → series bool
//@version=6
indicator("map.includes example")
a = map.new<string, float>()
a.put("open", open)
p = close
if map.contains(a, "open")
p := a.get("open")
plot(p)
map.copy(id) → map<keyType, valueType>
//@version=6
indicator("map.copy example")
a = map.new<string, int>()
a.put("example", 1)
b = map.copy(a)
a := map.new<string, int>()
a.put("example", 2)
plot(a.get("example"))
plot(b.get("example"))
id map.key in the id map.map.get(id, key) → <value_type>
//@version=6
indicator("map.get example")
a = map.new<int, int>()
size = 10
for i = 0 to size
a.put(i, size-i)
plot(map.get(a, 1))
id map. The resulting array is a copy and any changes to it are not reflected in the original map.map.keys(id) → array<type>
//@version=6
indicator("map.keys example")
a = map.new<string, float>()
a.put("open", open)
a.put("high", high)
a.put("low", low)
a.put("close", close)
keys = map.keys(a)
ohlc = 0.0
for key in keys
ohlc += a.get(key)
plot(ohlc/4)
keyType, and all values are of the valueType.valueType can be of any type except array<>, matrix<>, and map<>. User-defined types are allowed, even if they have array<>, matrix<>, or map<> as one of their fields.map.new<keyType, valueType>() → map<keyType, valueType>
//@version=6
indicator("map.new<string, int> example")
a = map.new<string, int>()
a.put("example", 1)
label.new(bar_index, close, str.tostring(a.get("example")))
key that's already in the map. The new pair replaces the existing pair with the key in such cases.id map.map.put(id, key, value) → <value_type>
//@version=6
indicator("map.put example")
a = map.new<string, float>()
map.put(a, "first", 10)
map.put(a, "second", 15)
prevFirst = map.put(a, "first", 20)
currFirst = a.get("first")
plot(prevFirst)
plot(currFirst)
key if the key was already present in the map, or na if the key is new.key that's already in the map. The new pair replaces the existing pair with the key in such cases.id2 map into the id map.map.put_all(id, id2) → void
//@version=6
indicator("map.put_all example")
a = map.new<string, float>()
b = map.new<string, float>()
a.put("first", 10)
a.put("second", 15)
b.put("third", 20)
map.put_all(a, b)
plot(a.get("third"))
id map.map.remove(id, key) → <value_type>
//@version=6
indicator("map.remove example")
a = map.new<string, color>()
a.put("firstColor", color.green)
oldColorValue = map.remove(a, "firstColor")
plot(close, color = oldColorValue)
key if the key was present in the map, or na if there was no such key.id map.map.size(id) → series int
//@version=6
indicator("map.size example")
a = map.new<int, int>()
size = 10
for i = 0 to size
a.put(i, size-i)
plot(map.size(a))
id map. The resulting array is a copy and any changes to it are not reflected in the original map.map.values(id) → array<type>
//@version=6
indicator("map.values example")
a = map.new<string, float>()
a.put("open", open)
a.put("high", high)
a.put("low", low)
a.put("close", close)
values = map.values(a)
ohlc = 0.0
for value in values
ohlc += value
plot(ohlc/4)
number is number if number >= 0, or -number otherwise.math.abs(number) → const int
math.abs(number) → input int
math.abs(number) → const float
math.abs(number) → simple int
math.abs(number) → input float
math.abs(number) → series int
math.abs(number) → simple float
math.abs(number) → series float
number.math.acos(angle) → const float
math.acos(angle) → input float
math.acos(angle) → simple float
math.acos(angle) → series float
math.asin(angle) → const float
math.asin(angle) → input float
math.asin(angle) → simple float
math.asin(angle) → series float
math.atan(angle) → const float
math.atan(angle) → input float
math.atan(angle) → simple float
math.atan(angle) → series float
math.avg(number0, number1, ...) → simple float
math.avg(number0, number1, ...) → series float
number up to the smallest whole number ("int" value) that is greater than or equal to it.math.ceil(number) → const int
math.ceil(number) → input int
math.ceil(number) → simple int
math.ceil(number) → series int
number.math.cos(angle) → const float
math.cos(angle) → input float
math.cos(angle) → simple float
math.cos(angle) → series float
number is e raised to the power of number, where e is Euler's number.math.exp(number) → const float
math.exp(number) → input float
math.exp(number) → simple float
math.exp(number) → series float
number.number down to the largest whole number ("int" value) that is less than or equal to it.math.floor(number) → const int
math.floor(number) → input int
math.floor(number) → simple int
math.floor(number) → series int
number.number > 0 is the unique y such that e^y = number.math.log(number) → const float
math.log(number) → input float
math.log(number) → simple float
math.log(number) → series float
number.number is the power to which 10 must be raised to obtain the number. 10^y = number.math.log10(number) → const float
math.log10(number) → input float
math.log10(number) → simple float
math.log10(number) → series float
number.math.max(number0, number1, ...) → const int
math.max(number0, number1, ...) → const float
math.max(number0, number1, ...) → input int
math.max(number0, number1, ...) → simple int
math.max(number0, number1, ...) → input float
math.max(number0, number1, ...) → series int
math.max(number0, number1, ...) → simple float
math.max(number0, number1, ...) → series float
//@version=6
indicator("math.max", overlay=true)
plot(math.max(close, open))
plot(math.max(close, math.max(open, 42)))
math.min(number0, number1, ...) → const int
math.min(number0, number1, ...) → const float
math.min(number0, number1, ...) → input int
math.min(number0, number1, ...) → simple int
math.min(number0, number1, ...) → input float
math.min(number0, number1, ...) → series int
math.min(number0, number1, ...) → simple float
math.min(number0, number1, ...) → series float
//@version=6
indicator("math.min", overlay=true)
plot(math.min(close, open))
plot(math.min(close, math.min(open, 42)))
math.pow(base, exponent) → const float
math.pow(base, exponent) → input float
math.pow(base, exponent) → simple float
math.pow(base, exponent) → series float
//@version=6
indicator("math.pow", overlay=true)
plot(math.pow(close, 2))
base raised to the power of exponent. If base is a series, it is calculated elementwise.math.random(min, max, seed) → series float
number rounded to the nearest integer, with ties rounding up. If the precision parameter is used, returns a float value rounded to that amount of decimal places.math.round(number) → const int
math.round(number) → input int
math.round(number) → simple int
math.round(number) → series int
math.round(number, precision) → const float
math.round(number, precision) → input float
math.round(number, precision) → simple float
math.round(number, precision) → series float
number rounded to the nearest integer, or according to precision.math.round_to_mintick(number) → simple float
math.round_to_mintick(number) → series float
number rounded to tick precision.number is zero if number is zero, 1.0 if number is greater than zero, -1.0 if number is less than zero.math.sign(number) → const float
math.sign(number) → input float
math.sign(number) → simple float
math.sign(number) → series float
math.sin(angle) → const float
math.sin(angle) → input float
math.sin(angle) → simple float
math.sin(angle) → series float
number >= 0 is the unique y >= 0 such that y^2 = number.math.sqrt(number) → const float
math.sqrt(number) → input float
math.sqrt(number) → simple float
math.sqrt(number) → series float
number.math.sum(source, length) → series float
source for length bars back.na values in the source series are ignored; the function calculates on the length quantity of non-na values.math.tan(angle) → const float
math.tan(angle) → input float
math.tan(angle) → simple float
math.tan(angle) → series float
math.todegrees(radians) → series float
math.toradians(degrees) → series float
column index of the id matrix.matrix.add_col(id, column, array_id) → void
matrix.columns(id). All existing columns with indices that are greater than or equal to this value increase their index by one. The default is matrix.columns(id).matrix.rows(id). By default, the function inserts a column of na values.//@version=6
indicator("`matrix.add_col()` Example 1")
// Create a 2x3 "int" matrix containing values `0`.
m = matrix.new<int>(2, 3, 0)
// Add a column with `na` values to the matrix.
matrix.add_col(m)
// Display matrix elements.
if barstate.islastconfirmedhistory
var t = table.new(position.top_right, 2, 2, color.green)
table.cell(t, 0, 0, "Matrix elements:")
table.cell(t, 0, 1, str.tostring(m))
//@version=6
indicator("`matrix.add_col()` Example 2")
if barstate.islastconfirmedhistory
// Create an empty matrix object.
var m = matrix.new<int>()
// Create an array with values `1` and `3`.
var a = array.from(1, 3)
// Add the `a` array as the first column of the empty matrix.
matrix.add_col(m, 0, a)
// Display matrix elements.
var t = table.new(position.top_right, 2, 2, color.green)
table.cell(t, 0, 0, "Matrix elements:")
table.cell(t, 0, 1, str.tostring(m))
row index of the id matrix.matrix.add_row(id, row, array_id) → void
matrix.rows(id). All existing rows with indices that are greater than or equal to this value increase their index by one. The default is matrix.rows(id).matrix.columns(id). By default, the function inserts a row of na values.//@version=6
indicator("`matrix.add_row()` Example 1")
// Create a 2x3 "int" matrix containing values `0`.
m = matrix.new<int>(2, 3, 0)
// Add a row with `na` values to the matrix.
matrix.add_row(m)
// Display matrix elements.
if barstate.islastconfirmedhistory
var t = table.new(position.top_right, 2, 2, color.green)
table.cell(t, 0, 0, "Matrix elements:")
table.cell(t, 0, 1, str.tostring(m))
//@version=6
indicator("`matrix.add_row()` Example 2")
if barstate.islastconfirmedhistory
// Create an empty matrix object.
var m = matrix.new<int>()
// Create an array with values `1` and `2`.
var a = array.from(1, 2)
// Add the `a` array as the first row of the empty matrix.
matrix.add_row(m, 0, a)
// Display matrix elements.
var t = table.new(position.top_right, 2, 2, color.green)
table.cell(t, 0, 0, "Matrix elements:")
table.cell(t, 0, 1, str.tostring(m))
matrix.avg(id) → series float
matrix.avg(id) → series int
//@version=6
indicator("`matrix.avg()` Example")
// Create a 2x2 matrix.
var m = matrix.new<int>(2, 2, na)
// Fill the matrix with values.
matrix.set(m, 0, 0, 1)
matrix.set(m, 0, 1, 2)
matrix.set(m, 1, 0, 3)
matrix.set(m, 1, 1, 4)
// Get the average value of the matrix.
var x = matrix.avg(m)
plot(x, 'Matrix average value')
id matrix.matrix.col(id, column) → array<type>
//@version=6
indicator("`matrix.col()` Example", "", true)
// Create a 2x3 "float" matrix from `hlc3` values.
m = matrix.new<float>(2, 3, hlc3)
// Return an array with the values of the first column of matrix `m`.
a = matrix.col(m, 0)
// Plot the first value from the array `a`.
plot(array.get(a, 0))
column values of the id matrix.matrix.columns(id) → series int
//@version=6
indicator("`matrix.columns()` Example")
// Create a 2x6 matrix with values `0`.
var m = matrix.new<int>(2, 6, 0)
// Get the quantity of columns in matrix `m`.
var x = matrix.columns(m)
// Display using a label.
if barstate.islastconfirmedhistory
label.new(bar_index, high, "Columns: " + str.tostring(x) + "\n" + str.tostring(m))
id.m2 matrix to the m1 matrix.matrix.concat(id1, id2) → matrix<type>
id1.//@version=6
indicator("`matrix.concat()` Example")
// Create a 2x4 "int" matrix containing values `0`.
m1 = matrix.new<int>(2, 4, 0)
// Create a 2x4 "int" matrix containing values `1`.
m2 = matrix.new<int>(2, 4, 1)
// Append matrix `m2` to `m1`.
matrix.concat(m1, m2)
// Display matrix elements.
if barstate.islastconfirmedhistory
var t = table.new(position.top_right, 2, 2, color.green)
table.cell(t, 0, 0, "Matrix Elements:")
table.cell(t, 0, 1, str.tostring(m1))
id1 matrix concatenated with the id2 matrix.matrix.copy(id) → matrix<type>
//@version=6
indicator("`matrix.copy()` Example")
// For efficiency, execute this code only once.
if barstate.islastconfirmedhistory
// Create a 2x3 "float" matrix with `1` values.
var m1 = matrix.new<float>(2, 3, 1)
// Copy the matrix to a new one.
// Note that unlike what `matrix.copy()` does,
// the simple assignment operation `m2 = m1`
// would NOT create a new copy of the `m1` matrix.
// It would merely create a copy of its ID referencing the same matrix.
var m2 = matrix.copy(m1)
// Display using a table.
var t = table.new(position.top_right, 5, 2, color.green)
table.cell(t, 0, 0, "Original Matrix:")
table.cell(t, 0, 1, str.tostring(m1))
table.cell(t, 1, 0, "Matrix Copy:")
table.cell(t, 1, 1, str.tostring(m2))
id matrix.matrix.det(id) → series float
matrix.det(id) → series int
//@version=6
indicator("`matrix.det` Example")
// Create a 2x2 matrix.
var m = matrix.new<float>(2, 2, na)
// Fill the matrix with values.
matrix.set(m, 0, 0, 3)
matrix.set(m, 0, 1, 7)
matrix.set(m, 1, 0, 1)
matrix.set(m, 1, 1, -4)
// Get the determinant of the matrix.
var x = matrix.det(m)
plot(x, 'Matrix determinant')
id matrix.id1 and id2, or of matrix id1 and an id2 scalar (a numerical value).matrix.diff(id1, id2) → matrix<int>
matrix.diff(id1, id2) → matrix<float>
//@version=6
indicator("`matrix.diff()` Example 1")
// For efficiency, execute this code only once.
if barstate.islastconfirmedhistory
// Create a 2x3 matrix containing values `5`.
var m1 = matrix.new<float>(2, 3, 5)
// Create a 2x3 matrix containing values `4`.
var m2 = matrix.new<float>(2, 3, 4)
// Create a new matrix containing the difference between matrices `m1` and `m2`.
var m3 = matrix.diff(m1, m2)
// Display using a table.
var t = table.new(position.top_right, 1, 2, color.green)
table.cell(t, 0, 0, "Difference between two matrices:")
table.cell(t, 0, 1, str.tostring(m3))
//@version=6
indicator("`matrix.diff()` Example 2")
// For efficiency, execute this code only once.
if barstate.islastconfirmedhistory
// Create a 2x3 matrix with values `4`.
var m1 = matrix.new<float>(2, 3, 4)
// Create a new matrix containing the difference between the `m1` matrix and the "int" value `1`.
var m2 = matrix.diff(m1, 1)
// Display using a table.
var t = table.new(position.top_right, 1, 2, color.green)
table.cell(t, 0, 0, "Difference between a matrix and a scalar:")
table.cell(t, 0, 1, str.tostring(m2))
id2 and id1.matrix.eigenvalues(id) → array<float>
matrix.eigenvalues(id) → array<int>
//@version=6
indicator("`matrix.eigenvalues()` Example")
// For efficiency, execute this code only once.
if barstate.islastconfirmedhistory
// Create a 2x2 matrix.
var m1 = matrix.new<int>(2, 2, na)
// Fill the matrix with values.
matrix.set(m1, 0, 0, 2)
matrix.set(m1, 0, 1, 4)
matrix.set(m1, 1, 0, 6)
matrix.set(m1, 1, 1, 8)
// Get the eigenvalues of the matrix.
tr = matrix.eigenvalues(m1)
// Display matrix elements.
var t = table.new(position.top_right, 2, 2, color.green)
table.cell(t, 0, 0, "Matrix elements:")
table.cell(t, 0, 1, str.tostring(m1))
table.cell(t, 1, 0, "Array of Eigenvalues:")
table.cell(t, 1, 1, str.tostring(tr))
id matrix.id matrix.matrix.eigenvectors(id) → matrix<float>
matrix.eigenvectors(id) → matrix<int>
//@version=6
indicator("`matrix.eigenvectors()` Example")
// For efficiency, execute this code only once.
if barstate.islastconfirmedhistory
// Create a 2x2 matrix
var m1 = matrix.new<int>(2, 2, 1)
// Fill the matrix with values.
matrix.set(m1, 0, 0, 2)
matrix.set(m1, 0, 1, 4)
matrix.set(m1, 1, 0, 6)
matrix.set(m1, 1, 1, 8)
// Get the eigenvectors of the matrix.
m2 = matrix.eigenvectors(m1)
// Display matrix elements.
var t = table.new(position.top_right, 2, 2, color.green)
table.cell(t, 0, 0, "Matrix Elements:")
table.cell(t, 0, 1, str.tostring(m1))
table.cell(t, 1, 0, "Matrix Eigenvectors:")
table.cell(t, 1, 1, str.tostring(m2))
id matrix.matrix.elements_count(id) → series int
id matrix defined by the indices from_column to to_column (not including it) and from_row to to_row(not including it) with the value.matrix.fill(id, value, from_row, to_row, from_column, to_column) → void
//@version=6
indicator("`matrix.fill()` Example")
// Create a 4x5 "int" matrix containing values `0`.
m = matrix.new<float>(4, 5, 0)
// Fill the intersection of rows 1 to 2 and columns 2 to 3 of the matrix with `hl2` values.
matrix.fill(m, hl2, 0, 2, 1, 3)
// Display using a label.
if barstate.islastconfirmedhistory
label.new(bar_index, high, str.tostring(m))
matrix.get(id, row, column) → <matrix_type>
//@version=6
indicator("`matrix.get()` Example", "", true)
// Create a 2x3 "float" matrix from the `hl2` values.
m = matrix.new<float>(2, 3, hl2)
// Return the value of the element at index [0, 0] of matrix `m`.
x = matrix.get(m, 0, 0)
plot(x)
row and column index of the id matrix.matrix.inv(id) → matrix<float>
matrix.inv(id) → matrix<int>
//@version=6
indicator("`matrix.inv()` Example")
// For efficiency, execute this code only once.
if barstate.islastconfirmedhistory
// Create a 2x2 matrix.
var m1 = matrix.new<int>(2, 2, na)
// Fill the matrix with values.
matrix.set(m1, 0, 0, 1)
matrix.set(m1, 0, 1, 2)
matrix.set(m1, 1, 0, 3)
matrix.set(m1, 1, 1, 4)
// Inverse of the matrix.
var m2 = matrix.inv(m1)
// Display matrix elements.
var t = table.new(position.top_right, 2, 2, color.green)
table.cell(t, 0, 0, "Original Matrix:")
table.cell(t, 0, 1, str.tostring(m1))
table.cell(t, 1, 0, "Inverse matrix:")
table.cell(t, 1, 1, str.tostring(m2))
id matrix.matrix.is_antidiagonal(id) → series bool
id matrix is anti-diagonal, false otherwise.matrix.is_antisymmetric(id) → series bool
id matrix is antisymmetric, false otherwise.matrix.is_binary(id) → series bool
id matrix is binary, false otherwise.matrix.is_diagonal(id) → series bool
id matrix is diagonal, false otherwise.matrix.is_identity(id) → series bool
id is an identity matrix, false otherwise.matrix.is_square(id) → series bool
id matrix is square, false otherwise.matrix.is_stochastic(id) → series bool
id matrix is stochastic, false otherwise.matrix.is_symmetric(id) → series bool
id matrix is symmetric, false otherwise.matrix.is_triangular(id) → series bool
id matrix is triangular, false otherwise.matrix.is_zero(id) → series bool
id matrix are zero, false otherwise.matrix.kron(id1, id2) → matrix<float>
matrix.kron(id1, id2) → matrix<int>
//@version=6
indicator("`matrix.kron()` Example")
// Display using a table.
if barstate.islastconfirmedhistory
// Create two matrices with default values `1` and `2`.
var m1 = matrix.new<float>(2, 2, 1)
var m2 = matrix.new<float>(2, 2, 2)
// Calculate the Kronecker product of the matrices.
var m3 = matrix.kron(m1, m2)
// Display matrix elements.
var t = table.new(position.top_right, 5, 2, color.green)
table.cell(t, 0, 0, "Matrix 1:")
table.cell(t, 0, 1, str.tostring(m1))
table.cell(t, 1, 1, "⊗")
table.cell(t, 2, 0, "Matrix 2:")
table.cell(t, 2, 1, str.tostring(m2))
table.cell(t, 3, 1, "=")
table.cell(t, 4, 0, "Kronecker product:")
table.cell(t, 4, 1, str.tostring(m3))
matrix.max(id) → series float
matrix.max(id) → series int
//@version=6
indicator("`matrix.max()` Example")
// Create a 2x2 matrix.
var m = matrix.new<int>(2, 2, na)
// Fill the matrix with values.
matrix.set(m, 0, 0, 1)
matrix.set(m, 0, 1, 2)
matrix.set(m, 1, 0, 3)
matrix.set(m, 1, 1, 4)
// Get the maximum value in the matrix.
var x = matrix.max(m)
plot(x, 'Matrix maximum value')
id matrix.matrix.median(id) → series float
matrix.median(id) → series int
//@version=6
indicator("`matrix.median()` Example")
// Create a 2x2 matrix.
m = matrix.new<int>(2, 2, na)
// Fill the matrix with values.
matrix.set(m, 0, 0, 1)
matrix.set(m, 0, 1, 2)
matrix.set(m, 1, 0, 3)
matrix.set(m, 1, 1, 4)
// Get the median of the matrix.
x = matrix.median(m)
plot(x, 'Median of the matrix')
matrix.min(id) → series float
matrix.min(id) → series int
//@version=6
indicator("`matrix.min()` Example")
// Create a 2x2 matrix.
var m = matrix.new<int>(2, 2, na)
// Fill the matrix with values.
matrix.set(m, 0, 0, 1)
matrix.set(m, 0, 1, 2)
matrix.set(m, 1, 0, 3)
matrix.set(m, 1, 1, 4)
// Get the minimum value from the matrix.
var x = matrix.min(m)
plot(x, 'Matrix minimum value')
id matrix.matrix.mode(id) → series float
matrix.mode(id) → series int
//@version=6
indicator("`matrix.mode()` Example")
// Create a 2x2 matrix.
var m = matrix.new<int>(2, 2, na)
// Fill the matrix with values.
matrix.set(m, 0, 0, 0)
matrix.set(m, 0, 1, 0)
matrix.set(m, 1, 0, 1)
matrix.set(m, 1, 1, 1)
// Get the mode of the matrix.
var x = matrix.mode(m)
plot(x, 'Mode of the matrix')
id matrix. If none exists, returns the smallest value instead.id1 and id2, or between an id1 matrix and an id2 scalar (a numerical value), or between an id1 matrix and an id2 vector (an array of values).matrix.mult(id1, id2) → array<int>
matrix.mult(id1, id2) → array<float>
matrix.mult(id1, id2) → matrix<int>
matrix.mult(id1, id2) → matrix<float>
//@version=6
indicator("`matrix.mult()` Example 1")
// For efficiency, execute this code only once.
if barstate.islastconfirmedhistory
// Create a 6x2 matrix containing values `5`.
var m1 = matrix.new<float>(6, 2, 5)
// Create a 2x3 matrix containing values `4`.
// Note that it must have the same quantity of rows as there are columns in the first matrix.
var m2 = matrix.new<float>(2, 3, 4)
// Create a new matrix from the multiplication of the two matrices.
var m3 = matrix.mult(m1, m2)
// Display using a table.
var t = table.new(position.top_right, 1, 2, color.green)
table.cell(t, 0, 0, "Product of two matrices:")
table.cell(t, 0, 1, str.tostring(m3))
//@version=6
indicator("`matrix.mult()` Example 2")
// For efficiency, execute this code only once.
if barstate.islastconfirmedhistory
// Create a 2x3 matrix containing values `4`.
var m1 = matrix.new<float>(2, 3, 4)
// Create a new matrix from the product of the two matrices.
scalar = 5
var m2 = matrix.mult(m1, scalar)
// Display using a table.
var t = table.new(position.top_right, 5, 2, color.green)
table.cell(t, 0, 0, "Matrix 1:")
table.cell(t, 0, 1, str.tostring(m1))
table.cell(t, 1, 1, "x")
table.cell(t, 2, 0, "Scalar:")
table.cell(t, 2, 1, str.tostring(scalar))
table.cell(t, 3, 1, "=")
table.cell(t, 4, 0, "Matrix 2:")
table.cell(t, 4, 1, str.tostring(m2))
//@version=6
indicator("`matrix.mult()` Example 3")
// For efficiency, execute this code only once.
if barstate.islastconfirmedhistory
// Create a 2x3 matrix containing values `4`.
var m1 = matrix.new<int>(2, 3, 4)
// Create an array of three elements.
var int[] a = array.from(1, 1, 1)
// Create a new matrix containing the product of the `m1` matrix and the `a` array.
var m3 = matrix.mult(m1, a)
// Display using a table.
var t = table.new(position.top_right, 5, 2, color.green)
table.cell(t, 0, 0, "Matrix 1:")
table.cell(t, 0, 1, str.tostring(m1))
table.cell(t, 1, 1, "x")
table.cell(t, 2, 0, "Value:")
table.cell(t, 2, 1, str.tostring(a, " "))
table.cell(t, 3, 1, "=")
table.cell(t, 4, 0, "Matrix 3:")
table.cell(t, 4, 1, str.tostring(m3))
id2 and id1.matrix.new<type>(rows, columns, initial_value) → matrix<type>
//@version=6
indicator("`matrix.new<type>()` Example 1")
// Create a 2x3 (2 rows x 3 columns) "int" matrix with values zero.
var m = matrix.new<int>(2, 3, 0)
// Display using a label.
if barstate.islastconfirmedhistory
label.new(bar_index, high, str.tostring(m))
//@version=6
indicator("`matrix.new<type>()` Example 2")
// Function to create a matrix whose rows are filled with array values.
matrixFromArray(int rows, int columns, array<float> data) =>
m = matrix.new<float>(rows, columns)
for i = 0 to rows <= 0 ? na : rows - 1
for j = 0 to columns <= 0 ? na : columns - 1
matrix.set(m, i, j, array.get(data, i * columns + j))
m
// Create a 3x3 matrix from an array of values.
var m1 = matrixFromArray(3, 3, array.from(1, 2, 3, 4, 5, 6, 7, 8, 9))
// Display using a label.
if barstate.islastconfirmedhistory
label.new(bar_index, high, str.tostring(m1))
input.text_area() field//@version=6
indicator("`matrix.new<type>()` Example 3")
// Function to create a matrix from a text string.
// Values in a row must be separated by a space. Each line is one row.
matrixFromInputArea(stringOfValues) =>
var rowsArray = str.split(stringOfValues, "\n")
var rows = array.size(rowsArray)
var cols = array.size(str.split(array.get(rowsArray, 0), " "))
var matrix = matrix.new<float>(rows, cols, na)
row = 0
for rowString in rowsArray
col = 0
values = str.split(rowString, " ")
for val in values
matrix.set(matrix, row, col, str.tonumber(val))
col += 1
row += 1
matrix
stringInput = input.text_area("1 2 3\n4 5 6\n7 8 9")
var m = matrixFromInputArea(stringInput)
// Display using a label.
if barstate.islastconfirmedhistory
label.new(bar_index, high, str.tostring(m))
//@version=6
indicator("`matrix.new<type>()` Example 4")
// Function to create a matrix with random values (0.0 to 1.0).
matrixRandom(int rows, int columns)=>
result = matrix.new<float>(rows, columns)
for i = 0 to rows - 1
for j = 0 to columns - 1
matrix.set(result, i, j, math.random())
result
// Create a 2x3 matrix with random values.
var m = matrixRandom(2, 3)
// Display using a label.
if barstate.islastconfirmedhistory
label.new(bar_index, high, str.tostring(m))
matrix.pinv(id) → matrix<float>
matrix.pinv(id) → matrix<int>
//@version=6
indicator("`matrix.pinv()` Example")
// For efficiency, execute this code only once.
if barstate.islastconfirmedhistory
// Create a 2x2 matrix.
var m1 = matrix.new<int>(2, 2, na)
// Fill the matrix with values.
matrix.set(m1, 0, 0, 1)
matrix.set(m1, 0, 1, 2)
matrix.set(m1, 1, 0, 3)
matrix.set(m1, 1, 1, 4)
// Pseudoinverse of the matrix.
var m2 = matrix.pinv(m1)
// Display matrix elements.
var t = table.new(position.top_right, 2, 2, color.green)
table.cell(t, 0, 0, "Original Matrix:")
table.cell(t, 0, 1, str.tostring(m1))
table.cell(t, 1, 0, "Pseudoinverse matrix:")
table.cell(t, 1, 1, str.tostring(m2))
id matrix.power times.matrix.pow(id, power) → matrix<float>
matrix.pow(id, power) → matrix<int>
//@version=6
indicator("`matrix.pow()` Example")
// Display using a table.
if barstate.islastconfirmedhistory
// Create a 2x2 matrix.
var m1 = matrix.new<int>(2, 2, 2)
// Calculate the power of three of the matrix.
var m2 = matrix.pow(m1, 3)
// Display matrix elements.
var t = table.new(position.top_right, 2, 2, color.green)
table.cell(t, 0, 0, "Original Matrix:")
table.cell(t, 0, 1, str.tostring(m1))
table.cell(t, 1, 0, "Matrix³:")
table.cell(t, 1, 1, str.tostring(m2))
id matrix by itself power times.matrix.rank(id) → series int
//@version=6
indicator("`matrix.rank()` Example")
// For efficiency, execute this code only once.
if barstate.islastconfirmedhistory
// Create a 2x2 matrix.
var m1 = matrix.new<int>(2, 2, na)
// Fill the matrix with values.
matrix.set(m1, 0, 0, 1)
matrix.set(m1, 0, 1, 2)
matrix.set(m1, 1, 0, 3)
matrix.set(m1, 1, 1, 4)
// Get the rank of the matrix.
r = matrix.rank(m1)
// Display matrix elements.
var t = table.new(position.top_right, 2, 2, color.green)
table.cell(t, 0, 0, "Matrix elements:")
table.cell(t, 0, 1, str.tostring(m1))
table.cell(t, 1, 0, "Rank of the matrix:")
table.cell(t, 1, 1, str.tostring(r))
id matrix.column index of the id matrix and returns an array containing the removed column's values.matrix.remove_col(id, column) → array<type>
//@version=6
indicator("matrix_remove_col", overlay = true)
// Create a 2x2 matrix with ones.
var matrixOrig = matrix.new<int>(2, 2, 1)
// Set values to the 'matrixOrig' matrix.
matrix.set(matrixOrig, 0, 1, 2)
matrix.set(matrixOrig, 1, 0, 3)
matrix.set(matrixOrig, 1, 1, 4)
// Create a copy of the 'matrixOrig' matrix.
matrixCopy = matrix.copy(matrixOrig)
// Remove the first column from the `matrixCopy` matrix.
arr = matrix.remove_col(matrixCopy, 0)
// Display matrix elements.
if barstate.islastconfirmedhistory
var t = table.new(position.top_right, 3, 2, color.green)
table.cell(t, 0, 0, "Original Matrix:")
table.cell(t, 0, 1, str.tostring(matrixOrig))
table.cell(t, 1, 0, "Removed Elements:")
table.cell(t, 1, 1, str.tostring(arr))
table.cell(t, 2, 0, "Result Matrix:")
table.cell(t, 2, 1, str.tostring(matrixCopy))
id matrix.row index of the id matrix and returns an array containing the removed row's values.matrix.remove_row(id, row) → array<type>
//@version=6
indicator("matrix_remove_row", overlay = true)
// Create a 2x2 "int" matrix containing values `1`.
var matrixOrig = matrix.new<int>(2, 2, 1)
// Set values to the 'matrixOrig' matrix.
matrix.set(matrixOrig, 0, 1, 2)
matrix.set(matrixOrig, 1, 0, 3)
matrix.set(matrixOrig, 1, 1, 4)
// Create a copy of the 'matrixOrig' matrix.
matrixCopy = matrix.copy(matrixOrig)
// Remove the first row from the matrix `matrixCopy`.
arr = matrix.remove_row(matrixCopy, 0)
// Display matrix elements.
if barstate.islastconfirmedhistory
var t = table.new(position.top_right, 3, 2, color.green)
table.cell(t, 0, 0, "Original Matrix:")
table.cell(t, 0, 1, str.tostring(matrixOrig))
table.cell(t, 1, 0, "Removed Elements:")
table.cell(t, 1, 1, str.tostring(arr))
table.cell(t, 2, 0, "Result Matrix:")
table.cell(t, 2, 1, str.tostring(matrixCopy))
id matrix.id matrix to rows x cols dimensions.matrix.reshape(id, rows, columns) → void
//@version=6
indicator("`matrix.reshape()` Example")
// For efficiency, execute this code only once.
if barstate.islastconfirmedhistory
// Create a 2x3 matrix.
var m1 = matrix.new<float>(2, 3)
// Fill the matrix with values.
matrix.set(m1, 0, 0, 1)
matrix.set(m1, 0, 1, 2)
matrix.set(m1, 0, 2, 3)
matrix.set(m1, 1, 0, 4)
matrix.set(m1, 1, 1, 5)
matrix.set(m1, 1, 2, 6)
// Copy the matrix to a new one.
var m2 = matrix.copy(m1)
// Reshape the copy to a 3x2.
matrix.reshape(m2, 3, 2)
// Display using a table.
var t = table.new(position.top_right, 2, 2, color.green)
table.cell(t, 0, 0, "Original matrix:")
table.cell(t, 0, 1, str.tostring(m1))
table.cell(t, 1, 0, "Reshaped matrix:")
table.cell(t, 1, 1, str.tostring(m2))
id. The first row and first column become the last, and the last become the first.matrix.reverse(id) → void
//@version=6
indicator("`matrix.reverse()` Example")
// For efficiency, execute this code only once.
if barstate.islastconfirmedhistory
// Copy the matrix to a new one.
var m1 = matrix.new<int>(2, 2, na)
// Fill the matrix with values.
matrix.set(m1, 0, 0, 1)
matrix.set(m1, 0, 1, 2)
matrix.set(m1, 1, 0, 3)
matrix.set(m1, 1, 1, 4)
// Copy matrix elements to a new matrix.
var m2 = matrix.copy(m1)
// Reverse the `m2` copy of the original matrix.
matrix.reverse(m2)
// Display using a table.
var t = table.new(position.top_right, 2, 2, color.green)
table.cell(t, 0, 0, "Original matrix:")
table.cell(t, 0, 1, str.tostring(m1))
table.cell(t, 1, 0, "Reversed matrix:")
table.cell(t, 1, 1, str.tostring(m2))
matrix.row(id, row) → array<type>
//@version=6
indicator("`matrix.row()` Example", "", true)
// Create a 2x3 "float" matrix from `hlc3` values.
m = matrix.new<float>(2, 3, hlc3)
// Return an array with the values of the first row of the matrix.
a = matrix.row(m, 0)
// Plot the first value from the array `a`.
plot(array.get(a, 0))
row values of the id matrix.matrix.rows(id) → series int
//@version=6
indicator("`matrix.rows()` Example")
// Create a 2x6 matrix with values `0`.
var m = matrix.new<int>(2, 6, 0)
// Get the quantity of rows in the matrix.
var x = matrix.rows(m)
// Display using a label.
if barstate.islastconfirmedhistory
label.new(bar_index, high, "Rows: " + str.tostring(x) + "\n" + str.tostring(m))
id.value to the element at the row and column of the id matrix.matrix.set(id, row, column, value) → void
//@version=6
indicator("`matrix.set()` Example")
// Create a 2x3 "int" matrix containing values `4`.
m = matrix.new<int>(2, 3, 4)
// Replace the value of element at row 1 and column 2 with value `3`.
matrix.set(m, 0, 1, 3)
// Display using a label.
if barstate.islastconfirmedhistory
label.new(bar_index, high, str.tostring(m))
id matrix following the sorted order of the values in the column.matrix.sort(id, column, order) → void
//@version=6
indicator("`matrix.sort()` Example")
// For efficiency, execute this code only once.
if barstate.islastconfirmedhistory
// Create a 2x2 matrix.
var m1 = matrix.new<float>(2, 2, na)
// Fill the matrix with values.
matrix.set(m1, 0, 0, 3)
matrix.set(m1, 0, 1, 4)
matrix.set(m1, 1, 0, 1)
matrix.set(m1, 1, 1, 2)
// Copy the matrix to a new one.
var m2 = matrix.copy(m1)
// Sort the rows of `m2` using the default arguments (first column and ascending order).
matrix.sort(m2)
// Display using a table.
if barstate.islastconfirmedhistory
var t = table.new(position.top_right, 2, 2, color.green)
table.cell(t, 0, 0, "Original matrix:")
table.cell(t, 0, 1, str.tostring(m1))
table.cell(t, 1, 0, "Sorted matrix:")
table.cell(t, 1, 1, str.tostring(m2))
id matrix within the specified indices.matrix.submatrix(id, from_row, to_row, from_column, to_column) → matrix<type>
//@version=6
indicator("`matrix.submatrix()` Example")
// For efficiency, execute this code only once.
if barstate.islastconfirmedhistory
// Create a 2x3 matrix matrix with values `0`.
var m1 = matrix.new<int>(2, 3, 0)
// Fill the matrix with values.
matrix.set(m1, 0, 0, 1)
matrix.set(m1, 0, 1, 2)
matrix.set(m1, 0, 2, 3)
matrix.set(m1, 1, 0, 4)
matrix.set(m1, 1, 1, 5)
matrix.set(m1, 1, 2, 6)
// Create a 2x2 submatrix of the `m1` matrix.
var m2 = matrix.submatrix(m1, 0, 2, 1, 3)
// Display using a table.
var t = table.new(position.top_right, 2, 2, color.green)
table.cell(t, 0, 0, "Original Matrix:")
table.cell(t, 0, 1, str.tostring(m1))
table.cell(t, 1, 0, "Submatrix:")
table.cell(t, 1, 1, str.tostring(m2))
id matrix defined by the from_row, to_row, from_column and to_column indices.id1 and id2, or of an id1 matrix and an id2 scalar (a numerical value).matrix.sum(id1, id2) → matrix<int>
matrix.sum(id1, id2) → matrix<float>
//@version=6
indicator("`matrix.sum()` Example 1")
// For efficiency, execute this code only once.
if barstate.islastconfirmedhistory
// Create a 2x3 matrix containing values `5`.
var m1 = matrix.new<float>(2, 3, 5)
// Create a 2x3 matrix containing values `4`.
var m2 = matrix.new<float>(2, 3, 4)
// Create a new matrix that sums matrices `m1` and `m2`.
var m3 = matrix.sum(m1, m2)
// Display using a table.
var t = table.new(position.top_right, 1, 2, color.green)
table.cell(t, 0, 0, "Sum of two matrices:")
table.cell(t, 0, 1, str.tostring(m3))
//@version=6
indicator("`matrix.sum()` Example 2")
// For efficiency, execute this code only once.
if barstate.islastconfirmedhistory
// Create a 2x3 matrix with values `4`.
var m1 = matrix.new<float>(2, 3, 4)
// Create a new matrix containing the sum of the `m1` matrix with the "int" value `1`.
var m2 = matrix.sum(m1, 1)
// Display using a table.
var t = table.new(position.top_right, 1, 2, color.green)
table.cell(t, 0, 0, "Sum of a matrix and a scalar:")
table.cell(t, 0, 1, str.tostring(m2))
id2 and id1.column1 and column2 in the id matrix.matrix.swap_columns(id, column1, column2) → void
//@version=6
indicator("`matrix.swap_columns()` Example")
// For efficiency, execute this code only once.
if barstate.islastconfirmedhistory
// Create a 2x2 matrix with ‘na’ values.
var m1 = matrix.new<int>(2, 2, na)
// Fill the matrix with values.
matrix.set(m1, 0, 0, 1)
matrix.set(m1, 0, 1, 2)
matrix.set(m1, 1, 0, 3)
matrix.set(m1, 1, 1, 4)
// Copy the matrix to a new one.
var m2 = matrix.copy(m1)
// Swap the first and second columns of the matrix copy.
matrix.swap_columns(m2, 0, 1)
// Display using a table.
var t = table.new(position.top_right, 2, 2, color.green)
table.cell(t, 0, 0, "Original matrix:")
table.cell(t, 0, 1, str.tostring(m1))
table.cell(t, 1, 0, "Swapped columns in copy:")
table.cell(t, 1, 1, str.tostring(m2))
row1 and row2 in the id matrix.matrix.swap_rows(id, row1, row2) → void
//@version=6
indicator("`matrix.swap_rows()` Example")
// For efficiency, execute this code only once.
if barstate.islastconfirmedhistory
// Create a 3x2 matrix with ‘na’ values.
var m1 = matrix.new<int>(3, 2, na)
// Fill the matrix with values.
matrix.set(m1, 0, 0, 1)
matrix.set(m1, 0, 1, 2)
matrix.set(m1, 1, 0, 3)
matrix.set(m1, 1, 1, 4)
matrix.set(m1, 2, 0, 5)
matrix.set(m1, 2, 1, 6)
// Copy the matrix to a new one.
var m2 = matrix.copy(m1)
// Swap the first and second rows of the matrix copy.
matrix.swap_rows(m2, 0, 1)
// Display using a table.
var t = table.new(position.top_right, 2, 2, color.green)
table.cell(t, 0, 0, "Original matrix:")
table.cell(t, 0, 1, str.tostring(m1))
table.cell(t, 1, 0, "Swapped rows in copy:")
table.cell(t, 1, 1, str.tostring(m2))
matrix.trace(id) → series float
matrix.trace(id) → series int
//@version=6
indicator("`matrix.trace()` Example")
// For efficiency, execute this code only once.
if barstate.islastconfirmedhistory
// Create a 2x2 matrix.
var m1 = matrix.new<int>(2, 2, na)
// Fill the matrix with values.
matrix.set(m1, 0, 0, 1)
matrix.set(m1, 0, 1, 2)
matrix.set(m1, 1, 0, 3)
matrix.set(m1, 1, 1, 4)
// Get the trace of the matrix.
tr = matrix.trace(m1)
// Display matrix elements.
var t = table.new(position.top_right, 2, 2, color.green)
table.cell(t, 0, 0, "Matrix elements:")
table.cell(t, 0, 1, str.tostring(m1))
table.cell(t, 1, 0, "Trace of the matrix:")
table.cell(t, 1, 1, str.tostring(tr))
id matrix.id. This interchanges the row and column index of each element.matrix.transpose(id) → matrix<type>
//@version=6
indicator("`matrix.transpose()` Example")
// For efficiency, execute this code only once.
if barstate.islastconfirmedhistory
// Create a 2x2 matrix.
var m1 = matrix.new<float>(2, 2, na)
// Fill the matrix with values.
matrix.set(m1, 0, 0, 1)
matrix.set(m1, 0, 1, 2)
matrix.set(m1, 1, 0, 3)
matrix.set(m1, 1, 1, 4)
// Create a transpose of the matrix.
var m2 = matrix.transpose(m1)
// Display using a table.
var t = table.new(position.top_right, 2, 2, color.green)
table.cell(t, 0, 0, "Original matrix:")
table.cell(t, 0, 1, str.tostring(m1))
table.cell(t, 1, 0, "Transposed matrix:")
table.cell(t, 1, 1, str.tostring(m2))
id matrix.max_bars_back(var, num) → void
//@version=6
indicator("max_bars_back")
close_() => close
depth() => 400
d = depth()
v = close_()
max_bars_back(v, 500)
out = if bar_index > 0
v[d]
else
v
plot(out)
minute(time, timezone) → series int
month(time, timezone) → series int
x is na.na(x) → simple bool
na(x) → series bool
//@version=6
indicator("na")
// Use the `na()` function to test for `na`.
plot(na(close[1]) ? close : close[1])
// ALTERNATIVE
// `nz()` also tests `close[1]` for `na`. It returns `close[1]` if it is not `na`, and `close` if it is.
plot(nz(close[1], close))
nz(source, replacement) → simple color
nz(source, replacement) → simple int
nz(source, replacement) → series color
nz(source, replacement) → series int
nz(source, replacement) → simple float
nz(source, replacement) → series float
source series. The default depends on the source type: 0 for "int", 0.0 for "float", or #00000000 for "color".//@version=6
indicator("nz", overlay=true)
plot(nz(ta.sma(close, 100)))
source if it is not na. If the value of source is na, returns zero, or the replacement argument when one is used.plot(series, title, color, linewidth, style, trackprice, histbase, offset, join, editable, show_last, display, format, precision, force_overlay) → plot
display.all - display.status_line will display the plot's information everywhere except in the script's status line. display.price_scale + display.status_line will display the plot only in the price scale and status line. When display arguments such as display.price_scale have user-controlled chart settings equivalents, the relevant plot information will only appear when all settings allow for it. Possible values: display.none, display.pane, display.data_window, display.price_scale, display.status_line, display.all. Optional. The default is display.all.format parameter of the indicator, and strategy functions. Optional. The default is the format value used by the indicator/strategy function. Possible values: format.price, format.percent, format.volume.precision parameter of the indicator and strategy functions. When the function's format parameter uses format.volume, the precision parameter will not affect the result, as the decimal precision rules defined by format.volume supersede other precision settings. Optional. The default is the precision value used by the indicator/strategy function.//@version=6
indicator("plot")
plot(high+low, title='Title', color=color.new(#00ffaa, 70), linewidth=2, style=plot.style_area, offset=15, trackprice=true)
// You may fill the background between any two plots with a fill() function:
p1 = plot(open)
p2 = plot(close)
fill(p1, p2, color=color.new(color.green, 90))
plotarrow(series, title, colorup, colordown, offset, minheight, maxheight, editable, show_last, display, format, precision, force_overlay) → void
display.all - display.status_line will display the plot's information everywhere except in the script's status line. display.price_scale + display.status_line will display the plot only in the price scale and status line. When display arguments such as display.price_scale have user-controlled chart settings equivalents, the relevant plot information will only appear when all settings allow for it. Possible values: display.none, display.pane, display.data_window, display.price_scale, display.status_line, display.all. Optional. The default is display.all.format parameter of the indicator, and strategy functions. Optional. The default is the format value used by the indicator/strategy function. Possible values: format.price, format.percent, format.volume.precision parameter of the indicator and strategy functions. When the function's format parameter uses format.volume, the precision parameter will not affect the result, as the decimal precision rules defined by format.volume supersede other precision settings. Optional. The default is the precision value used by the indicator/strategy function.//@version=6
indicator("plotarrow example", overlay=true)
codiff = close - open
plotarrow(codiff, colorup=color.new(color.teal,40), colordown=color.new(color.orange, 40))
plotbar(open, high, low, close, title, color, editable, show_last, display, format, precision, force_overlay) → void
display.all - display.status_line will display the plot's information everywhere except in the script's status line. display.price_scale + display.status_line will display the plot only in the price scale and status line. When display arguments such as display.price_scale have user-controlled chart settings equivalents, the relevant plot information will only appear when all settings allow for it. Possible values: display.none, display.pane, display.data_window, display.price_scale, display.status_line, display.all. Optional. The default is display.all.format parameter of the indicator, and strategy functions. Optional. The default is the format value used by the indicator/strategy function. Possible values: format.price, format.percent, format.volume.precision parameter of the indicator and strategy functions. When the function's format parameter uses format.volume, the precision parameter will not affect the result, as the decimal precision rules defined by format.volume supersede other precision settings. Optional. The default is the precision value used by the indicator/strategy function.//@version=6
indicator("plotbar example", overlay=true)
plotbar(open, high, low, close, title='Title', color = open < close ? color.green : color.red)
plotcandle(open, high, low, close, title, color, wickcolor, editable, show_last, bordercolor, display, format, precision, force_overlay) → void
display.all - display.status_line will display the plot's information everywhere except in the script's status line. display.price_scale + display.status_line will display the plot only in the price scale and status line. When display arguments such as display.price_scale have user-controlled chart settings equivalents, the relevant plot information will only appear when all settings allow for it. Possible values: display.none, display.pane, display.data_window, display.price_scale, display.status_line, display.all. Optional. The default is display.all.format parameter of the indicator, and strategy functions. Optional. The default is the format value used by the indicator/strategy function. Possible values: format.price, format.percent, format.volume.precision parameter of the indicator and strategy functions. When the function's format parameter uses format.volume, the precision parameter will not affect the result, as the decimal precision rules defined by format.volume supersede other precision settings. Optional. The default is the precision value used by the indicator/strategy function.//@version=6
indicator("plotcandle example", overlay=true)
plotcandle(open, high, low, close, title='Title', color = open < close ? color.green : color.red, wickcolor=color.black)
plotchar(series, title, char, location, color, offset, text, textcolor, editable, size, show_last, display, format, precision, force_overlay) → void
display.all - display.status_line will display the plot's information everywhere except in the script's status line. display.price_scale + display.status_line will display the plot only in the price scale and status line. When display arguments such as display.price_scale have user-controlled chart settings equivalents, the relevant plot information will only appear when all settings allow for it. Possible values: display.none, display.pane, display.data_window, display.price_scale, display.status_line, display.all. Optional. The default is display.all.format parameter of the indicator, and strategy functions. Optional. The default is the format value used by the indicator/strategy function. Possible values: format.price, format.percent, format.volume.precision parameter of the indicator and strategy functions. When the function's format parameter uses format.volume, the precision parameter will not affect the result, as the decimal precision rules defined by format.volume supersede other precision settings. Optional. The default is the precision value used by the indicator/strategy function.//@version=6
indicator("plotchar example", overlay=true)
data = close >= open
plotchar(data, char='❄')
plotshape(series, title, style, location, color, offset, text, textcolor, editable, size, show_last, display, format, precision, force_overlay) → void
display.all - display.status_line will display the plot's information everywhere except in the script's status line. display.price_scale + display.status_line will display the plot only in the price scale and status line. When display arguments such as display.price_scale have user-controlled chart settings equivalents, the relevant plot information will only appear when all settings allow for it. Possible values: display.none, display.pane, display.data_window, display.price_scale, display.status_line, display.all. Optional. The default is display.all.format parameter of the indicator, and strategy functions. Optional. The default is the format value used by the indicator/strategy function. Possible values: format.price, format.percent, format.volume.precision parameter of the indicator and strategy functions. When the function's format parameter uses format.volume, the precision parameter will not affect the result, as the decimal precision rules defined by format.volume supersede other precision settings. Optional. The default is the precision value used by the indicator/strategy function.//@version=6
indicator("plotshape example 1", overlay=true)
data = close >= open
plotshape(data, style=shape.xcross)
id doesn't exist.polyline.delete(id) → void
points array with line segments. The segments in the drawing can be straight or curved depending on the curved parameter.polyline.new(points, curved, closed, xloc, line_color, fill_color, line_style, line_width, force_overlay) → series polyline
points array using curved line segments. Optional. The default is false.points array, resulting in a closed polyline. Optional. The default is false.points array that the polyline will use for its x-coordinates. If xloc.bar_index, the polyline will use the index field from each point. If xloc.bar_time, it will use the time field. Optional. The default is xloc.bar_index.//@version=6
indicator("Polylines example", overlay = true)
//@variable If `true`, connects all points in the polyline with curved line segments.
bool curvedInput = input.bool(false, "Curve Polyline")
//@variable If `true`, connects the first point in the polyline to the last point.
bool closedInput = input.bool(true, "Close Polyline")
//@variable The color of the space filled by the polyline.
color fillcolor = input.color(color.new(color.blue, 90), "Fill Color")
// Time and price inputs for the polyline's points.
p1x = input.time(0, "p1", confirm = true, inline = "p1")
p1y = input.price(0, " ", confirm = true, inline = "p1")
p2x = input.time(0, "p2", confirm = true, inline = "p2")
p2y = input.price(0, " ", confirm = true, inline = "p2")
p3x = input.time(0, "p3", confirm = true, inline = "p3")
p3y = input.price(0, " ", confirm = true, inline = "p3")
p4x = input.time(0, "p4", confirm = true, inline = "p4")
p4y = input.price(0, " ", confirm = true, inline = "p4")
p5x = input.time(0, "p5", confirm = true, inline = "p5")
p5y = input.price(0, " ", confirm = true, inline = "p5")
if barstate.islastconfirmedhistory
//@variable An array of `chart.point` objects for the new polyline.
var points = array.new<chart.point>()
// Push new `chart.point` instances into the `points` array.
points.push(chart.point.from_time(p1x, p1y))
points.push(chart.point.from_time(p2x, p2y))
points.push(chart.point.from_time(p3x, p3y))
points.push(chart.point.from_time(p4x, p4y))
points.push(chart.point.from_time(p5x, p5y))
// Add labels for each `chart.point` in `points`.
l1p1 = label.new(points.get(0), text = "p1", xloc = xloc.bar_time, color = na)
l1p2 = label.new(points.get(1), text = "p2", xloc = xloc.bar_time, color = na)
l2p1 = label.new(points.get(2), text = "p3", xloc = xloc.bar_time, color = na)
l2p2 = label.new(points.get(3), text = "p4", xloc = xloc.bar_time, color = na)
// Create a new polyline that connects each `chart.point` in the `points` array, starting from the first.
polyline.new(points, curved = curvedInput, closed = closedInput, fill_color = fillcolor, xloc = xloc.bar_time)
polyline.*() functions.from currency to another in the to currency.request.currency_rate(from, to, ignore_invalid_currency) → series float
//@version=6
indicator("Close in British Pounds")
rate = request.currency_rate(syminfo.currency, "GBP")
plot(close * rate)
from and to arguments are equal, function returns 1. Please note that using this variable/function can cause indicator repainting.request.dividends(ticker, field, gaps, lookahead, ignore_invalid_symbol, currency) → series float
currency.* namespace (e.g., currency.USD or currency.USDT). The default is syminfo.currency.//@version=6
indicator("request.dividends")
s1 = request.dividends("NASDAQ:BELFA")
plot(s1)
s2 = request.dividends("NASDAQ:BELFA", dividends.net, gaps=barmerge.gaps_on, lookahead=barmerge.lookahead_on)
plot(s2)
request.earnings(ticker, field, gaps, lookahead, ignore_invalid_symbol, currency) → series float
currency.* namespace (e.g., currency.USD or currency.USDT). The default is syminfo.currency.//@version=6
indicator("request.earnings")
s1 = request.earnings("NASDAQ:BELFA")
plot(s1)
s2 = request.earnings("NASDAQ:BELFA", earnings.actual, gaps=barmerge.gaps_on, lookahead=barmerge.lookahead_on)
plot(s2)
request.economic(country_code, field, gaps, ignore_invalid_symbol) → series float
//@version=6
indicator("US GDP")
e = request.economic("US", "GDP")
plot(e)
{country_code}{field} as the ticker. The name of US GDP data is thus "ECONOMIC:USGDP".request.financial(symbol, financial_id, period, gaps, ignore_invalid_symbol, currency) → series float
currency.* namespace (e.g., currency.USD or currency.USDT). The default is syminfo.currency.//@version=6
indicator("request.financial")
f = request.financial("NASDAQ:MSFT", "ACCOUNTS_PAYABLE", "FY")
plot(f)
request.quandl(ticker, gaps, index, ignore_invalid_symbol) → series float
//@version=6
indicator("request.quandl")
f = request.quandl("CFTC/SB_FO_ALL", barmerge.gaps_off, 0)
plot(f)
request.security(symbol, timeframe, expression, gaps, lookahead, ignore_invalid_symbol, currency, calc_bars_count) → series <type>
ticker.* namespace.timeframe specified in the indicator function. To request data from a different timeframe, supply a valid timeframe string. See here to learn about specifying timeframe strings.ta.change(close) / (high - low), a function call that does not use Pine Script® drawings, an object, a collection, or a tuple of expressions.expression argument like in close[1] will introduce future leak in scripts, as the function will then return the close price before it is actually known in the current context. As is explained in the User Manual's page on Repainting this will produce misleading results.200 are not converted. The conversion rate for monetary values depends on the previous daily value of a corresponding currency pair from the most popular exchange. A spread symbol is used if no exchange provides the rate directly. Possible values: a "string" representing a valid currency code (e.g., "USD" or "USDT") or a constant from the currency.* namespace (e.g., currency.USD or currency.USDT). The default is syminfo.currency.expression as if these values are the only available data, which might improve calculation speed in some cases. Optional. The default is 100,000, which is the limit for all non-professional TradingView plans.//@version=6
indicator("Simple `request.security()` calls")
// Returns 1D close of the current symbol.
dailyClose = request.security(syminfo.tickerid, "1D", close)
plot(dailyClose)
// Returns the close of "AAPL" from the same timeframe as currently open on the chart.
aaplClose = request.security("AAPL", timeframe.period, close)
plot(aaplClose)
//@version=6
indicator("Advanced `request.security()` calls")
// This calculates a 10-period moving average on the active chart.
sma = ta.sma(close, 10)
// This sends the `sma` calculation for execution in the context of the "AAPL" symbol at a "240" (4 hours) timeframe.
aaplSma = request.security("AAPL", "240", sma)
plot(aaplSma)
// To avoid differences on historical and realtime bars, you can use this technique, which only returns a value from the higher timeframe on the bar after it completes:
indexHighTF = barstate.isrealtime ? 1 : 0
indexCurrTF = barstate.isrealtime ? 0 : 1
nonRepaintingClose = request.security(syminfo.tickerid, "1D", close[indexHighTF])[indexCurrTF]
plot(nonRepaintingClose, "Non-repainting close")
// Returns the 1H close of "AAPL", extended session included. The value is dividend-adjusted.
extendedTicker = ticker.modify("NASDAQ:AAPL", session = session.extended, adjustment = adjustment.dividends)
aaplExtAdj = request.security(extendedTicker, "60", close)
plot(aaplExtAdj)
// Returns the result of a user-defined function.
// The `max` variable is mutable, but we can pass it to `request.security()` because it is wrapped in a function.
allTimeHigh(source) =>
var max = source
max := math.max(max, source)
allTimeHigh1D = request.security(syminfo.tickerid, "1D", allTimeHigh(high))
// By using a tuple `expression`, we obtain several values with only one `request.security()` call.
[open1D, high1D, low1D, close1D, ema1D] = request.security(syminfo.tickerid, "1D", [open, high, low, close, ta.ema(close, 10)])
plotcandle(open1D, high1D, low1D, close1D)
plot(ema1D)
// Returns an array containing the OHLC values of the chart's symbol from the 1D timeframe.
ohlcArray = request.security(syminfo.tickerid, "1D", array.from(open, high, low, close))
plotcandle(array.get(ohlcArray, 0), array.get(ohlcArray, 1), array.get(ohlcArray, 2), array.get(ohlcArray, 3))
expression.request.*() function calls. A call is unique only if it does not call the same function with the same arguments.request.*() function to evaluate the same expression from the same context with different calc_bars_count values, the second call requests the same number of historical bars as the first. For example, if a script calls request.security("AAPL", "", close, calc_bars_count = 3) after it calls request.security("AAPL", "", close, calc_bars_count = 5), the second call also uses five bars of historical data, not three.request.() call can be inherited if it is not specified precisely, i.e., if the symbol argument is an empty string or syminfo.tickerid. Similarly, the timeframe of a request.() call can be inherited if the timeframe argument is an empty string or timeframe.period. These values are normally taken from the chart on which the script is running. However, if request.*() function A is called from within the expression of request.*() function B, then function A can inherit the values from function B. See here for more information.timeframe argument of "1" typically returns an array with five elements representing the value of the expression on each 1-minute bar, ordered by time with the earliest value first.request.security_lower_tf(symbol, timeframe, expression, ignore_invalid_symbol, currency, ignore_invalid_timeframe, calc_bars_count) → array<type>
ticker.* namespace.timeframe specified in the indicator function. To request data from a different timeframe, supply a valid timeframe string. See here to learn about specifying timeframe strings.ta.change(close) / (high - low), a function call that does not use Pine Script® drawings, an object, or a tuple of expressions. Collections are not allowed unless they are within the fields of an object200 are not converted. The conversion rate for monetary values depends on the previous daily value of a corresponding currency pair from the most popular exchange. A spread symbol is used if no exchange provides the rate directly. Possible values: a "string" representing a valid currency code (e.g., "USD" or "USDT") or a constant from the currency.* namespace (e.g., currency.USD or currency.USDT). The default is syminfo.currency.timeframe used in the function call. If false, the script will halt and throw a runtime error. If true, the function will return na and execution will continue. Optional. The default is false.expression as if these values are the only available data, which might improve calculation speed in some cases. Optional. The default is 100,000, which is the limit for all non-professional TradingView plans.//@version=6
indicator("`request.security_lower_tf()` Example", overlay = true)
// If the current chart timeframe is set to 120 minutes, then the `arrayClose` array will contain two 'close' values from the 60 minute timeframe for each bar.
arrClose = request.security_lower_tf(syminfo.tickerid, "60", close)
if bar_index == last_bar_index - 1
label.new(bar_index, high, str.tostring(arrClose))
expression, or a tuple of these.request.*() function calls. A call is unique only if it does not call the same function with the same arguments.request.*() function to evaluate the same expression from the same context with different calc_bars_count values, the second call requests the same number of historical bars as the first. For example, if a script calls request.security("AAPL", "", close, calc_bars_count = 3) after it calls request.security("AAPL", "", close, calc_bars_count = 5), the second call also uses five bars of historical data, not three.request.() call can be inherited if it is not specified precisely, i.e., if the symbol argument is an empty string or syminfo.tickerid. Similarly, the timeframe of a request.() call can be inherited if the timeframe argument is an empty string or timeframe.period. These values are normally taken from the chart that the script is running on. However, if request.*() function A is called from within the expression of request.*() function B, then function A can inherit the values from function B. See here for more information.request.seed(source, symbol, expression, ignore_invalid_symbol, calc_bars_count) → series <type>
ta.sma(close, 100), a non-mutable variable previously calculated in the script, a function call that does not use Pine Script® drawings, an array, a matrix, or a tuple. Mutable variables are not allowed, unless they are enclosed in the body of a function used in the expression.expression as if these values are the only available data, which might improve calculation speed in some cases. Optional. The default is 100,000, which is the limit for all non-professional TradingView plans.//@version=6
indicator("BTC Development Activity")
[devAct, devActSMA] = request.seed("seed_crypto_santiment", "BTC_DEV_ACTIVITY", [close, ta.sma(close, 10)])
plot(devAct, "BTC Development Activity")
plot(devActSMA, "BTC Development Activity SMA10", color = color.yellow)
request.splits(ticker, field, gaps, lookahead, ignore_invalid_symbol) → series float
//@version=6
indicator("request.splits")
s1 = request.splits("NASDAQ:BELFA", splits.denominator)
plot(s1)
s2 = request.splits("NASDAQ:BELFA", splits.denominator, gaps=barmerge.gaps_on, lookahead=barmerge.lookahead_on)
plot(s2)
message argument.runtime.error(message) → void
second(time, timezone) → series int
source string contains the str substring, false otherwise.str.contains(source, str) → const bool
str.contains(source, str) → simple bool
str.contains(source, str) → series bool
//@version=6
indicator("str.contains")
// If the current chart is a continuous futures chart, e.g “BTC1!”, then the function will return true, false otherwise.
var isFutures = str.contains(syminfo.tickerid, "!")
plot(isFutures ? 1 : 0)
str was found in the source string, false otherwise.source string ends with the substring specified in str, false otherwise.str.endswith(source, str) → const bool
str.endswith(source, str) → simple bool
str.endswith(source, str) → series bool
source string ends with the substring specified in str, false otherwise.str.format(formatString, arg0, arg1, ...) → simple string
str.format(formatString, arg0, arg1, ...) → series string
//@version=6
indicator("str.format", overlay=true)
// The format specifier inside the curly braces accepts certain modifiers:
// - Specify the number of decimals to display:
s1 = str.format("{0,number,#.#}", 1.34) // returns: 1.3
label.new(bar_index, close, text=s1)
// - Round a float value to an integer:
s2 = str.format("{0,number,integer}", 1.34) // returns: 1
label.new(bar_index - 1, close, text=s2)
// - Display a number in currency:
s3 = str.format("{0,number,currency}", 1.34) // returns: $1.34
label.new(bar_index - 2, close, text=s3)
// - Display a number as a percentage:
s4 = str.format("{0,number,percent}", 0.5) // returns: 50%
label.new(bar_index - 3, close, text=s4)
// EXAMPLES WITH SEVERAL ARGUMENTS
// returns: Number 1 is not equal to 4
s5 = str.format("Number {0} is not {1} to {2}", 1, "equal", 4)
label.new(bar_index - 4, close, text=s5)
// returns: 1.34 != 1.3
s6 = str.format("{0} != {0, number, #.#}", 1.34)
label.new(bar_index - 5, close, text=s6)
// returns: 1 is equal to 1, but 2 is equal to 2
s7 = str.format("{0, number, integer} is equal to 1, but {1, number, integer} is equal to 2", 1.34, 1.52)
label.new(bar_index - 6, close, text=s7)
// returns: The cash turnover amounted to $1,340,000.00
s8 = str.format("The cash turnover amounted to {0, number, currency}", 1340000)
label.new(bar_index - 7, close, text=s8)
// returns: Expected return is 10% - 20%
s9 = str.format("Expected return is {0, number, percent} - {1, number, percent}", 0.1, 0.2)
label.new(bar_index - 8, close, text=s9)
formatString argument can contain single quote characters ('). However, one must pair all single quotes in that string to avoid unexpected formatting results.time timestamp into a string formatted according to format and timezone.str.format_time(time, format, timezone) → series string
time in the returned string. All letters used in the string, except those escaped by single quotation marks ', are considered formatting tokens and will be used as a formatting instruction. Refer to the Remarks section for a list of the most useful tokens. Optional. The default is "yyyy-MM-dd'T'HH:mm:ssZ", which represents the ISO 8601 standard.//@version=6
indicator("str.format_time")
if timeframe.change("1D")
formattedTime = str.format_time(time, "yyyy-MM-dd HH:mm", syminfo.timezone)
label.new(bar_index, high, formattedTime)
M, d, h, H, m and s tokens can all be doubled to generate leading zeros. For example, the month of January will display as 1 with M, or 01 with MM.yy to output the last two digits of the year or yyyy to output all four. Year 2000 will be 00 with yy or 2000 with yyyy.m, which stands for minute.11 in this format.23 in this format.+ or -.str.length(string) → const int
str.length(string) → simple int
str.length(string) → series int
str.lower(source) → const string
str.lower(source) → simple string
str.lower(source) → series string
source string if it matches a regex regular expression, an empty string otherwise.str.match(source, regex) → simple string
str.match(source, regex) → series string
//@version=6
indicator("str.match")
s = input.string("It's time to sell some NASDAQ:AAPL!")
// finding first substring that matches regular expression "[\w]+:[\w]+"
var string tickerid = str.match(s, "[\\w]+:[\\w]+")
if barstate.islastconfirmedhistory
label.new(bar_index, high, text = tickerid) // "NASDAQ:AAPL"
source string if it matches a regex regular expression, an empty string otherwise.source string.regex string needs to be escaped with additional backslash, e.g. "\\d" stands for regular expression "\d".str string in the source string, 'na' otherwise.str.pos(source, str) → const int
str.pos(source, str) → simple int
str.pos(source, str) → series int
str string in the source string.source string repeated repeat times with the separator injected between each repeated instance.str.repeat(source, repeat, separator) → const string
str.repeat(source, repeat, separator) → input string
str.repeat(source, repeat, separator) → simple string
str.repeat(source, repeat, separator) → series string
source string. Must be greater than or equal to 0.//@version=6
indicator("str.repeat")
repeat = str.repeat("?", 3, ",") // Returns "?,?,?"
label.new(bar_index,close,repeat)
target string replaced by the replacement string, where N is specified in occurrence.str.replace(source, target, replacement, occurrence) → const string
str.replace(source, target, replacement, occurrence) → simple string
str.replace(source, target, replacement, occurrence) → series string
//@version=6
indicator("str.replace")
var source = "FTX:BTCUSD / FTX:BTCEUR"
// Replace first occurrence of "FTX" with "BINANCE" replacement string
var newSource = str.replace(source, "FTX", "BINANCE", 0)
if barstate.islastconfirmedhistory
// Display "BINANCE:BTCUSD / FTX:BTCEUR"
label.new(bar_index, high, text = newSource)
str.replace_all(source, target, replacement) → simple string
str.replace_all(source, target, replacement) → series string
str.split(string, separator) → array<string>
source string starts with the substring specified in str, false otherwise.str.startswith(source, str) → const bool
str.startswith(source, str) → simple bool
str.startswith(source, str) → series bool
source string starts with the substring specified in str, false otherwise.source string. The substring begins with the character at the index specified by begin_pos and extends to 'end_pos - 1' of the source string.str.substring(source, begin_pos, end_pos) → const string
str.substring(source, begin_pos, end_pos) → simple string
str.substring(source, begin_pos, end_pos) → series string
source string.//@version=6
indicator("str.substring", overlay = true)
sym= input.symbol("NASDAQ:AAPL")
pos = str.pos(sym, ":") // Get position of ":" character
tkr= str.substring(sym, pos+1) // "AAPL"
if barstate.islastconfirmedhistory
label.new(bar_index, high, text = tkr)
begin_pos is equal to end_pos, the function returns an empty string.string to its "float" equivalent.str.tonumber(string) → const float
str.tonumber(string) → input float
str.tonumber(string) → simple float
str.tonumber(string) → series float
string. If the value is not a properly formed integer or floating point value, the function returns na.str.tostring(value, format) → simple string
str.tostring(value, format) → series string
str.tostring(value) → simple string
str.tostring(value) → series string
value argument.value argument is a string, it is returned as is.value is na, the function returns the string "NaN".source.str.trim(source) → const string
str.trim(source) → input string
str.trim(source) → simple string
str.trim(source) → series string
//@version=6
indicator("str.trim")
trim = str.trim(" abc ") // Returns "abc"
label.new(bar_index,close,trim)
source is na.str.upper(source) → const string
str.upper(source) → simple string
str.upper(source) → series string
strategy(title, shorttitle, overlay, format, precision, scale, pyramiding, calc_on_order_fills, calc_on_every_tick, max_bars_back, backtest_fill_limits_assumption, default_qty_type, default_qty_value, initial_capital, currency, slippage, commission_type, commission_value, process_orders_on_close, close_entries_rule, margin_long, margin_short, explicit_plot_zorder, max_lines_count, max_labels_count, max_boxes_count, calc_bars_count, risk_free_rate, use_bar_magnifier, fill_orders_on_standard_ohlc, max_polylines_count, dynamic_requests, behind_chart) → void
shorttitle argument is used, and becomes the publication's default title when publishing the script.title argument in most chart-related windows. Optional. The default is the argument used for title.format is set to format.inherit and precision is specified, the format will instead be set to format.price. When the function's format parameter uses format.volume, the precision parameter will not affect the result, as the decimal precision rules defined by format.volume supersede other precision settings. Optional. The default is inherited from the precision of the chart's symbol.overlay = true. Optional. By default, the script uses the same scale as the chart.[] history-referencing operator. The required buffer size is automatically detected by the Pine Script® runtime. Using this parameter is only necessary when a runtime error occurs because automatic detection fails. More information on the underlying mechanics of the historical buffer can be found in our Help Center. Optional. The default is 0.default_qty_value. Possible values are: strategy.fixed for contracts/shares/lots, strategy.cash for currency amounts, or strategy.percent_of_equity for a percentage of available equity. This setting can also be changed in the strategy's "Settings/Properties" tab. Optional. The default is strategy.fixed.default_qty_type parameter. This setting can also be changed in the strategy's "Settings/Properties" tab. Optional. The default is 1.currency. Optional. The default is 1000000.currency into the chart symbol's currency. The conversion rate depends on the previous daily value of a corresponding currency pair from the most popular exchange. A spread symbol is used if no exchange provides the rate directly. Possible values: a "string" representing a valid currency code (e.g., "USD" or "USDT") or a constant from the currency.* namespace (e.g., currency.USD or currency.USDT). The default is syminfo.currency.slippage is set to 5, a long market order will enter at 5 * 0.01 = 0.05 points above the actual price. This setting can also be changed in the strategy's "Settings/Properties" tab. Optional. The default is 0.commission_value expresses: strategy.commission.percent for a percentage of the cash volume of the order, strategy.commission.cash_per_contract for currency per contract, strategy.commission.cash_per_order for currency per order. This setting can also be changed in the strategy's "Settings/Properties" tab. Optional. The default is strategy.commission.percent.commission_type parameter. This setting can also be changed in the strategy's "Settings/Properties" tab. Optional. The default is 0.from_entry parameter of the strategy.exit function. "FIFO" can only be used with stocks, futures and US forex (NFA Compliance Rule 2-43b), while "ANY" is allowed in non-US forex. Optional. The default is "FIFO".plot*() functions, fill, and hline. Optional. The default is false.request.*() namespace. Dynamic request.*() calls are allowed within the local scopes of conditional structures (e.g., if), loops (e.g., for), and exported functions. Additionally, such calls allow "series" arguments for many of their parameters. Optional. The default is true. See the User Manual's Dynamic requests section for more information.//@version=6
strategy("My strategy", overlay = true)
// Enter long by market if current open is greater than previous high.
if open > high[1]
strategy.entry("Long", strategy.long, 1)
// Generate a full exit bracket (profit 10 points, loss 5 points per contract) from the entry named "Long".
strategy.exit("Exit", "Long", profit = 10, loss = 5)
calc_on_every_tick = true parameter may calculate differently on historical and realtime bars, which causes repainting.strategy.closedtrades.*() functions return na for trades opened or closed by removed orders. To retrieve the index of the oldest available closed trade, use the strategy.closedtrades.first_index variable.id argument cancels all of them. If a script calls this command with an id representing the ID of a filled order, it has no effect.strategy.cancel(id) → void
//@version=6
strategy(title = "Order cancellation demo")
conditionForBuy = open > high[1]
if conditionForBuy
strategy.entry("Long", strategy.long, 1, limit = low) // Enter long using limit order at low price of current bar if `conditionForBuy` is `true`.
if not conditionForBuy
strategy.cancel("Long") // Cancel the entry order with name "Long" if `conditionForBuy` is `false`.
strategy.cancel_all() → void
//@version=6
strategy(title = "Cancel all orders demo")
conditionForBuy1 = open > high[1]
if conditionForBuy1
strategy.entry("Long entry 1", strategy.long, 1, limit = low) // Enter long using a limit order if `conditionForBuy1` is `true`.
conditionForBuy2 = conditionForBuy1 and open[1] > high[2]
float lowest2 = ta.lowest(low, 2)
if conditionForBuy2
strategy.entry("Long entry 2", strategy.long, 1, limit = lowest2) // Enter long using a limit order if `conditionForBuy2` is `true`.
conditionForStopTrading = open < lowest2
if conditionForStopTrading
strategy.cancel_all() // Cancel both limit orders if `conditionForStopTrading` is `true`.
id argument.strategy.close(id, comment, qty, qty_percent, alert_message, immediately, disable_alert) → void
qty_percent to determine the order size. The default is na, which means the order size depends on the qty_percent value.id entry identifier. The command ignores this parameter if the qty value is not na. The default is 100.{{strategy.order.alert_message}} placeholder, the alert message replaces the placeholder with this text. The default is an empty string.//@version=6
strategy("Partial close strategy")
// Calculate a 14-bar and 28-bar moving average of `close` prices.
float sma14 = ta.sma(close, 14)
float sma28 = ta.sma(close, 28)
// Place a market order to enter a long position when `sma14` crosses over `sma28`.
if ta.crossover(sma14, sma28)
strategy.entry("My Long Entry ID", strategy.long)
// Place a market order to close the long trade when `sma14` crosses under `sma28`.
if ta.crossunder(sma14, sma28)
strategy.close("My Long Entry ID", "50% market close", qty_percent = 50)
// Plot the position size.
plot(strategy.position_size)
close_entries_rule in the strategy declaration statement is "FIFO" (default), a strategy.close call exits from the position starting with the first open trade. This behavior applies even if the id value is the entry ID of different open trades. However, in that case, the maximum exit order size still depends on the trades opened by orders with the id identifier. For more information, see this section of our User Manual.strategy.close_all(comment, alert_message, immediately, disable_alert) → void
{{strategy.order.alert_message}} placeholder, the alert message replaces the placeholder with this text. The default is an empty string.//@version=6
strategy("Multi-entry close strategy")
// Calculate a 14-bar and 28-bar moving average of `close` prices.
float sma14 = ta.sma(close, 14)
float sma28 = ta.sma(close, 28)
// Place a market order to enter a long trade every time `sma14` crosses over `sma28`.
if ta.crossover(sma14, sma28)
strategy.order("My Long Entry ID " + str.tostring(strategy.opentrades), strategy.long)
// Place a market order to close the entire position every 500 bars.
if bar_index % 500 == 0
strategy.close_all()
// Plot the position size.
plot(strategy.position_size)
strategy.closedtrades.commission(trade_num) → series float
//@version=6
strategy("`strategy.closedtrades.commission` Example", commission_type = strategy.commission.percent, commission_value = 0.1)
// Strategy calls to enter long trades every 15 bars and exit long trades every 20 bars.
if bar_index % 15 == 0
strategy.entry("Long", strategy.long)
if bar_index % 20 == 0
strategy.close("Long")
// Plot total fees for the latest closed trade.
plot(strategy.closedtrades.commission(strategy.closedtrades - 1))
strategy.closedtrades.entry_bar_index(trade_num) → series int
//@version=6
strategy("strategy.closedtrades.entry_bar_index Example")
// Enter long trades on three rising bars; exit on two falling bars.
if ta.rising(close, 3)
strategy.entry("Long", strategy.long)
if ta.falling(close, 2)
strategy.close("Long")
// Function that calculates the average amount of bars in a trade.
avgBarsPerTrade() =>
sumBarsPerTrade = 0
for tradeNo = 0 to strategy.closedtrades - 1
// Loop through all closed trades, starting with the oldest.
sumBarsPerTrade += strategy.closedtrades.exit_bar_index(tradeNo) - strategy.closedtrades.entry_bar_index(tradeNo) + 1
result = nz(sumBarsPerTrade / strategy.closedtrades)
plot(avgBarsPerTrade())
trade_num.strategy.closedtrades.entry_comment(trade_num) → series string
//@version=6
strategy("`strategy.closedtrades.entry_comment()` Example", overlay = true)
stopPrice = open * 1.01
longCondition = ta.crossover(ta.sma(close, 14), ta.sma(close, 28))
if (longCondition)
strategy.entry("Long", strategy.long, stop = stopPrice, comment = str.tostring(stopPrice, "#.####"))
strategy.exit("EXIT", trail_points = 1000, trail_offset = 0)
var testTable = table.new(position.top_right, 1, 3, color.orange, border_width = 1)
if barstate.islastconfirmedhistory or barstate.isrealtime
table.cell(testTable, 0, 0, 'Last closed trade:')
table.cell(testTable, 0, 1, "Order stop price value: " + strategy.closedtrades.entry_comment(strategy.closedtrades - 1))
table.cell(testTable, 0, 2, "Actual Entry Price: " + str.tostring(strategy.closedtrades.entry_price(strategy.closedtrades - 1)))
strategy.closedtrades.entry_id(trade_num) → series string
//@version=6
strategy("strategy.closedtrades.entry_id Example", overlay = true)
// Enter a short position and close at the previous to last bar.
if bar_index == 1
strategy.entry("Short at bar #" + str.tostring(bar_index), strategy.short)
if bar_index == last_bar_index - 2
strategy.close_all()
// Display ID of the last entry position.
if barstate.islastconfirmedhistory
label.new(last_bar_index, high, "Last Entry ID is: " + strategy.closedtrades.entry_id(strategy.closedtrades - 1))
strategy.closedtrades.entry_price(trade_num) → series float
//@version=6
strategy("strategy.closedtrades.entry_price Example 1")
// Strategy calls to enter long trades every 15 bars and exit long trades every 20 bars.
if bar_index % 15 == 0
strategy.entry("Long", strategy.long)
if bar_index % 20 == 0
strategy.close("Long")
// Return the entry price for the latest entry.
entryPrice = strategy.closedtrades.entry_price(strategy.closedtrades - 1)
plot(entryPrice, "Long entry price")
// Calculates the average profit percentage for all closed trades.
//@version=6
strategy("strategy.closedtrades.entry_price Example 2")
// Strategy calls to create single short and long trades
if bar_index == last_bar_index - 15
strategy.entry("Long Entry", strategy.long)
else if bar_index == last_bar_index - 10
strategy.close("Long Entry")
strategy.entry("Short", strategy.short)
else if bar_index == last_bar_index - 5
strategy.close("Short")
// Calculate profit for both closed trades.
profitPct = 0.0
for tradeNo = 0 to strategy.closedtrades - 1
entryP = strategy.closedtrades.entry_price(tradeNo)
exitP = strategy.closedtrades.exit_price(tradeNo)
profitPct += (exitP - entryP) / entryP * strategy.closedtrades.size(tradeNo) * 100
// Calculate average profit percent for both closed trades.
avgProfitPct = nz(profitPct / strategy.closedtrades)
plot(avgProfitPct)
strategy.closedtrades.entry_time(trade_num) → series int
//@version=6
strategy("strategy.closedtrades.entry_time Example", overlay = true)
// Enter long trades on three rising bars; exit on two falling bars.
if ta.rising(close, 3)
strategy.entry("Long", strategy.long)
if ta.falling(close, 2)
strategy.close("Long")
// Calculate the average trade duration
avgTradeDuration() =>
sumTradeDuration = 0
for i = 0 to strategy.closedtrades - 1
sumTradeDuration += strategy.closedtrades.exit_time(i) - strategy.closedtrades.entry_time(i)
result = nz(sumTradeDuration / strategy.closedtrades)
// Display average duration converted to seconds and formatted using 2 decimal points
if barstate.islastconfirmedhistory
label.new(bar_index, high, str.tostring(avgTradeDuration() / 1000, "#.##") + " seconds")
strategy.closedtrades.exit_bar_index(trade_num) → series int
//@version=6
strategy("strategy.closedtrades.exit_bar_index Example 1")
// Strategy calls to place a single short trade. We enter the trade at the first bar and exit the trade at 10 bars before the last chart bar.
if bar_index == 0
strategy.entry("Short", strategy.short)
if bar_index == last_bar_index - 10
strategy.close("Short")
// Calculate the amount of bars since the last closed trade.
barsSinceClosed = strategy.closedtrades > 0 ? bar_index - strategy.closedtrades.exit_bar_index(strategy.closedtrades - 1) : na
plot(barsSinceClosed, "Bars since last closed trade")
// Calculates the average amount of bars per trade.
//@version=6
strategy("strategy.closedtrades.exit_bar_index Example 2")
// Enter long trades on three rising bars; exit on two falling bars.
if ta.rising(close, 3)
strategy.entry("Long", strategy.long)
if ta.falling(close, 2)
strategy.close("Long")
// Function that calculates the average amount of bars per trade.
avgBarsPerTrade() =>
sumBarsPerTrade = 0
for tradeNo = 0 to strategy.closedtrades - 1
// Loop through all closed trades, starting with the oldest.
sumBarsPerTrade += strategy.closedtrades.exit_bar_index(tradeNo) - strategy.closedtrades.entry_bar_index(tradeNo) + 1
result = nz(sumBarsPerTrade / strategy.closedtrades)
plot(avgBarsPerTrade())
trade_num.strategy.closedtrades.exit_comment(trade_num) → series string
//@version=6
strategy("`strategy.closedtrades.exit_comment()` Example", overlay = true)
longCondition = ta.crossover(ta.sma(close, 14), ta.sma(close, 28))
if (longCondition)
strategy.entry("Long", strategy.long)
strategy.exit("Exit", stop = open * 0.95, limit = close * 1.05, trail_points = 100, trail_offset = 0, comment_profit = "TP", comment_loss = "SL", comment_trailing = "TRAIL")
exitStats() =>
int slCount = 0
int tpCount = 0
int trailCount = 0
if strategy.closedtrades > 0
for i = 0 to strategy.closedtrades - 1
switch strategy.closedtrades.exit_comment(i)
"TP" => tpCount += 1
"SL" => slCount += 1
"TRAIL" => trailCount += 1
[slCount, tpCount, trailCount]
var testTable = table.new(position.top_right, 1, 4, color.orange, border_width = 1)
if barstate.islastconfirmedhistory
[slCount, tpCount, trailCount] = exitStats()
table.cell(testTable, 0, 0, "Closed trades (" + str.tostring(strategy.closedtrades) +") stats:")
table.cell(testTable, 0, 1, "Stop Loss: " + str.tostring(slCount))
table.cell(testTable, 0, 2, "Take Profit: " + str.tostring(tpCount))
table.cell(testTable, 0, 3, "Trailing Stop: " + str.tostring(trailCount))
strategy.closedtrades.exit_id(trade_num) → series string
//@version=6
strategy("strategy.closedtrades.exit_id Example", overlay = true)
// Strategy calls to create single short and long trades
if bar_index == last_bar_index - 15
strategy.entry("Long Entry", strategy.long)
else if bar_index == last_bar_index - 10
strategy.entry("Short Entry", strategy.short)
// When a new open trade is detected then we create the exit strategy corresponding with the matching entry id
// We detect the correct entry id by determining if a position is long or short based on the position quantity
if ta.change(strategy.opentrades) != 0
posSign = strategy.opentrades.size(strategy.opentrades - 1)
strategy.exit(posSign > 0 ? "SL Long Exit" : "SL Short Exit", strategy.opentrades.entry_id(strategy.opentrades - 1), stop = posSign > 0 ? high - ta.tr : low + ta.tr)
// When a new closed trade is detected then we place a label above the bar with the exit info
if ta.change(strategy.closedtrades) != 0
msg = "Trade closed by: " + strategy.closedtrades.exit_id(strategy.closedtrades - 1)
label.new(bar_index, high + (3 * ta.tr), msg)
strategy.closedtrades.exit_price(trade_num) → series float
//@version=6
strategy("strategy.closedtrades.exit_price Example 1")
// We are creating a long trade every 5 bars
if bar_index % 5 == 0
strategy.entry("Long", strategy.long)
strategy.close("Long")
// Return the exit price from the latest closed trade.
exitPrice = strategy.closedtrades.exit_price(strategy.closedtrades - 1)
plot(exitPrice, "Long exit price")
// Calculates the average profit percentage for all closed trades.
//@version=6
strategy("strategy.closedtrades.exit_price Example 2")
// Strategy calls to create single short and long trades.
if bar_index == last_bar_index - 15
strategy.entry("Long Entry", strategy.long)
else if bar_index == last_bar_index - 10
strategy.close("Long Entry")
strategy.entry("Short", strategy.short)
else if bar_index == last_bar_index - 5
strategy.close("Short")
// Calculate profit for both closed trades.
profitPct = 0.0
for tradeNo = 0 to strategy.closedtrades - 1
entryP = strategy.closedtrades.entry_price(tradeNo)
exitP = strategy.closedtrades.exit_price(tradeNo)
profitPct += (exitP - entryP) / entryP * strategy.closedtrades.size(tradeNo) * 100
// Calculate average profit percent for both closed trades.
avgProfitPct = nz(profitPct / strategy.closedtrades)
plot(avgProfitPct)
strategy.closedtrades.exit_time(trade_num) → series int
//@version=6
strategy("strategy.closedtrades.exit_time Example 1")
// Enter long trades on three rising bars; exit on two falling bars.
if ta.rising(close, 3)
strategy.entry("Long", strategy.long)
if ta.falling(close, 2)
strategy.close("Long")
// Calculate the average trade duration.
avgTradeDuration() =>
sumTradeDuration = 0
for i = 0 to strategy.closedtrades - 1
sumTradeDuration += strategy.closedtrades.exit_time(i) - strategy.closedtrades.entry_time(i)
result = nz(sumTradeDuration / strategy.closedtrades)
// Display average duration converted to seconds and formatted using 2 decimal points.
if barstate.islastconfirmedhistory
label.new(bar_index, high, str.tostring(avgTradeDuration() / 1000, "#.##") + " seconds")
// Reopens a closed trade after X seconds.
//@version=6
strategy("strategy.closedtrades.exit_time Example 2")
// Strategy calls to emulate a single long trade at the first bar.
if bar_index == 0
strategy.entry("Long", strategy.long)
reopenPositionAfter(timeSec) =>
if strategy.closedtrades > 0
if time - strategy.closedtrades.exit_time(strategy.closedtrades - 1) >= timeSec * 1000
strategy.entry("Long", strategy.long)
// Reopen last closed position after 120 sec.
reopenPositionAfter(120)
if ta.change(strategy.opentrades) != 0
strategy.exit("Long", stop = low * 0.9, profit = high * 2.5)
strategy.closedtrades.max_drawdown(trade_num) → series float
//@version=6
strategy("`strategy.closedtrades.max_drawdown` Example")
// Strategy calls to enter long trades every 15 bars and exit long trades every 20 bars.
if bar_index % 15 == 0
strategy.entry("Long", strategy.long)
if bar_index % 20 == 0
strategy.close("Long")
// Get the biggest max trade drawdown value from all of the closed trades.
maxTradeDrawDown() =>
maxDrawdown = 0.0
for tradeNo = 0 to strategy.closedtrades - 1
maxDrawdown := math.max(maxDrawdown, strategy.closedtrades.max_drawdown(tradeNo))
result = maxDrawdown
plot(maxTradeDrawDown(), "Biggest max drawdown")
Lowest Value During Trade / (Entry Price x Quantity) * 100.strategy.closedtrades.max_drawdown_percent(trade_num) → series float
strategy.closedtrades.max_runup(trade_num) → series float
//@version=6
strategy("`strategy.closedtrades.max_runup` Example")
// Strategy calls to enter long trades every 15 bars and exit long trades every 20 bars.
if bar_index % 15 == 0
strategy.entry("Long", strategy.long)
if bar_index % 20 == 0
strategy.close("Long")
// Get the biggest max trade runup value from all of the closed trades.
maxTradeRunUp() =>
maxRunup = 0.0
for tradeNo = 0 to strategy.closedtrades - 1
maxRunup := math.max(maxRunup, strategy.closedtrades.max_runup(tradeNo))
result = maxRunup
plot(maxTradeRunUp(), "Max trade runup")
Highest Value During Trade / (Entry Price x Quantity) * 100.strategy.closedtrades.max_runup_percent(trade_num) → series float
strategy.closedtrades.profit(trade_num) → series float
//@version=6
strategy("`strategy.closedtrades.profit` Example")
// Strategy calls to enter long trades every 15 bars and exit long trades every 20 bars.
if bar_index % 15 == 0
strategy.entry("Long", strategy.long)
if bar_index % 20 == 0
strategy.close("Long")
// Calculate average gross profit by adding the difference between gross profit and commission.
avgGrossProfit() =>
sumGrossProfit = 0.0
for tradeNo = 0 to strategy.closedtrades - 1
sumGrossProfit += strategy.closedtrades.profit(tradeNo) - strategy.closedtrades.commission(tradeNo)
result = nz(sumGrossProfit / strategy.closedtrades)
plot(avgGrossProfit(), "Average gross profit")
strategy.closedtrades.profit_percent(trade_num) → series float
strategy.closedtrades.size(trade_num) → series float
//@version=6
strategy("`strategy.closedtrades.size` Example 1")
// We calculate the max amt of shares we can buy.
amtShares = math.floor(strategy.equity / close)
// Strategy calls to enter long trades every 15 bars and exit long trades every 20 bars
if bar_index % 15 == 0
strategy.entry("Long", strategy.long, qty = amtShares)
if bar_index % 20 == 0
strategy.close("Long")
// Plot the number of contracts traded in the last closed trade.
plot(strategy.closedtrades.size(strategy.closedtrades - 1), "Number of contracts traded")
// Calculates the average profit percentage for all closed trades.
//@version=6
strategy("`strategy.closedtrades.size` Example 2")
// Strategy calls to enter long trades every 15 bars and exit long trades every 20 bars.
if bar_index % 15 == 0
strategy.entry("Long", strategy.long)
if bar_index % 20 == 0
strategy.close("Long")
// Calculate profit for both closed trades.
profitPct = 0.0
for tradeNo = 0 to strategy.closedtrades - 1
entryP = strategy.closedtrades.entry_price(tradeNo)
exitP = strategy.closedtrades.exit_price(tradeNo)
profitPct += (exitP - entryP) / entryP * strategy.closedtrades.size(tradeNo) * 100
// Calculate average profit percent for both closed trades.
avgProfitPct = nz(profitPct / strategy.closedtrades)
plot(avgProfitPct)
strategy.convert_to_account(value) → series float
//@version=6
strategy("`strategy.convert_to_account` Example 1", currency = currency.EUR)
plot(close, "Close price using default currency")
plot(strategy.convert_to_account(close), "Close price converted to strategy currency")
// Calculates the "Buy and hold return" using your account's currency.
//@version=6
strategy("`strategy.convert_to_account` Example 2", currency = currency.EUR)
dateInput = input.time(timestamp("20 Jul 2021 00:00 +0300"), "From Date", confirm = true)
buyAndHoldReturnPct(fromDate) =>
if time >= fromDate
money = close * syminfo.pointvalue
var initialBal = strategy.convert_to_account(money)
(strategy.convert_to_account(money) - initialBal) / initialBal * 100
plot(buyAndHoldReturnPct(dateInput))
strategy.convert_to_symbol(value) → series float
//@version=6
strategy("`strategy.convert_to_symbol` Example", currency = currency.EUR)
// Calculate the max qty we can buy using current chart's currency.
calcContracts(accountMoney) =>
math.floor(strategy.convert_to_symbol(accountMoney) / syminfo.pointvalue / close)
// Return max qty we can buy using 300 euros
qt = calcContracts(300)
// Strategy calls to enter long trades every 15 bars and exit long trades every 20 bars using our custom qty.
if bar_index % 15 == 0
strategy.entry("Long", strategy.long, qty = qt)
if bar_index % 20 == 0
strategy.close("Long")
fill_price value. The calculation depends on several strategy properties, including default_qty_type, default_qty_value, currency, and other parameters in the strategy function and their representation in the "Properties" tab of the strategy's settings.strategy.default_entry_qty(fill_price) → series float
//@version=6
strategy("Supertrend Strategy", overlay = true, default_qty_type = strategy.percent_of_equity, default_qty_value = 15)
//@variable The length of the ATR calculation.
atrPeriod = input(10, "ATR Length")
//@variable The ATR multiplier.
factor = input.float(3.0, "Factor", step = 0.01)
//@variable The tick offset of the stop order.
stopOffsetInput = input.int(100, "Tick offset for entry stop")
// Get the direction of the SuperTrend.
[_, direction] = ta.supertrend(factor, atrPeriod)
if ta.change(direction) < 0
//@variable The stop price of the entry order.
stopPrice = close + syminfo.mintick * stopOffsetInput
//@variable The expected default fill quantity at the `stopPrice`. This value may not reflect actual qty of the filled order, because fill price may be different.
calculatedQty = strategy.default_entry_qty(stopPrice)
strategy.entry("My Long Entry Id", strategy.long, stop = stopPrice)
label.new(bar_index, stopPrice, str.format("Stop set at {0}\nExpected qty at {0}: {1}", math.round_to_mintick(stopPrice), calculatedQty))
if ta.change(direction) > 0
strategy.close_all()
qty of 10 units, using the strategy.entry function to simulate a short order with a qty of 5 will prompt the script to sell 15 units to reverse the position. This function will still return 5 in such a case since it doesn't consider an open trade.qty value in the function call.id exists, a call to this command modifies that order.limit and stop parameters. If the call does not contain limit or stop arguments, it creates a market order that executes on the next tick. If the call specifies a limit value but no stop value, it places a limit order that executes after the market price reaches the limit value or a better price (lower for buy orders and higher for sell orders). If the call specifies a stop value but no limit value, it places a stop order that executes after the market price reaches the stop value or a worse price (higher for buy orders and lower for sell orders). If the call contains limit and stop arguments, it creates a stop-limit order, which generates a limit order at the limit price only after the market price reaches the stop value or a worse price.pyramiding parameter of the strategy declaration statement. Pyramiding specifies the number of concurrent open entries allowed per position. For example, with pyramiding = 3, the strategy can have up to three open trades, and the command cannot create orders to open additional trades until at least one existing trade closes.qty of 5 and a direction of strategy.short triggers the sale of 10 shares to close the long position and open a new five-share short position. Users can change this behavior by specifying an allowed direction with the strategy.risk_allow_entry_in function.strategy.entry(id, direction, qty, limit, stop, oca_name, oca_type, comment, alert_message, disable_alert) → void
comment value.default_qty_type and default_qty_value parameters of the strategy declaration statement to determine the quantity.stop value is also specified. The default is na, which means the resulting order is not of the limit or stop-limit type.limit value is also specified. The default is na, which means the resulting order is not of the stop or stop-limit type.oca_name and oca_type parameters executes, that order affects all unfilled orders in the group. The default is an empty string, which means the order does not belong to an OCA group.oca_name and oca_type values executes. Possible values: strategy.oca.cancel, strategy.oca.reduce, strategy.oca.none. The default is strategy.oca.none.id. The default is an empty string.{{strategy.order.alert_message}} placeholder, the alert message replaces the placeholder with this text. The default is an empty string.//@version=6
strategy("Market order strategy", overlay = true)
// Calculate a 14-bar and 28-bar moving average of `close` prices.
float sma14 = ta.sma(close, 14)
float sma28 = ta.sma(close, 28)
// Place a market order to close the short trade and enter a long position when `sma14` crosses over `sma28`.
if ta.crossover(sma14, sma28)
strategy.entry("My Long Entry ID", strategy.long)
// Place a market order to close the long trade and enter a short position when `sma14` crosses under `sma28`.
if ta.crossunder(sma14, sma28)
strategy.entry("My Short Entry ID", strategy.short)
//@version=6
strategy("Limit order strategy", overlay=true, margin_long=100, margin_short=100)
//@variable The distance from the `close` price for each limit order.
float limitOffsetInput = input.int(100, "Limit offset, in ticks", 1) * syminfo.mintick
//@function Draws a label and line at the specified `price` to visualize a limit order's level.
drawLimit(float price, bool isLong) =>
color col = isLong ? color.blue : color.red
label.new(
bar_index, price, (isLong ? "Long" : "Short") + " limit order created",
style = label.style_label_right, color = col, textcolor = color.white
)
line.new(bar_index, price, bar_index + 1, price, extend = extend.right, style = line.style_dashed, color = col)
//@function Stops the `l` line from extending further.
method stopExtend(line l) =>
l.set_x2(bar_index)
l.set_extend(extend.none)
// Initialize two `line` variables to reference limit line IDs.
var line longLimit = na
var line shortLimit = na
// Calculate a 14-bar and 28-bar moving average of `close` prices.
float sma14 = ta.sma(close, 14)
float sma28 = ta.sma(close, 28)
if ta.crossover(sma14, sma28)
// Cancel any unfilled sell orders with the specified ID.
strategy.cancel("My Short Entry ID")
//@variable The limit price level. Its value is `limitOffsetInput` ticks below the current `close`.
float limitLevel = close - limitOffsetInput
// Place a long limit order to close the short trade and enter a long position at the `limitLevel`.
strategy.entry("My Long Entry ID", strategy.long, limit = limitLevel)
// Make new drawings for the long limit and stop extending the `shortLimit` line.
longLimit := drawLimit(limitLevel, isLong = true)
shortLimit.stopExtend()
if ta.crossunder(sma14, sma28)
// Cancel any unfilled buy orders with the specified ID.
strategy.cancel("My Long Entry ID")
//@variable The limit price level. Its value is `limitOffsetInput` ticks above the current `close`.
float limitLevel = close + limitOffsetInput
// Place a short limit order to close the long trade and enter a short position at the `limitLevel`.
strategy.entry("My Short Entry ID", strategy.short, limit = limitLevel)
// Make new drawings for the short limit and stop extending the `shortLimit` line.
shortLimit := drawLimit(limitLevel, isLong = false)
longLimit.stopExtend()
id exist, calls to this command modify those orders. This command can generate more than one type of exit order, depending on the specified parameters. However, it does not create market orders. To exit from a position with a market order, use strategy.close or strategy.close_all.profit or limit argument, it creates take-profit orders to exit from applicable trades at the determined price levels or better values (higher for long trades and lower for short ones). If the call contains loss or stop arguments, it creates stop-loss orders to exit from applicable trades at the determined levels or worse values (lower for long trades and higher for short ones). Calling this command with profit or limit and loss or stop arguments creates an order bracket with both order types.trail_price or trail_points argument and a trail_offset argument. A trailing stop order activates when the price moves trail_points ticks past the entry price or touches the trail_price level. Once activated, the stop follows trail_offset ticks behind the market price each time the trade's profit reaches a new high. The stop does not move when the trade does not achieve a new best value.qty of 20, that call's orders reserve 20 contracts out of the position. A second call can close a maximum of 30 contracts, even if its qty is 50 and one of its orders executes first. This behavior does not affect the orders from other commands, such as strategy.close or strategy.order.strategy.exit(id, from_entry, qty, qty_percent, profit, limit, loss, stop, trail_price, trail_points, trail_offset, oca_name, comment, comment_profit, comment_loss, comment_trailing, alert_message, alert_profit, alert_loss, alert_trailing, disable_alert) → void
comment* argument that applies to the filled order.qty_percent to determine the order size. The exit orders reserve this quantity from the position, meaning other calls to this command cannot close this portion until the strategy fills or cancels those orders. The default is na, which means the order size depends on the qty_percent value.qty value is not na. The default is 100.profit ticks away from the entry price in the favorable direction. The order executes at the calculated price or a better value. If this parameter and limit are not na, the command places a take-profit order only at the price level expected to trigger an exit first. The default is na.profit are not na, the command places a take-profit order only at the price level expected to trigger an exit first. The default is na.loss ticks away from the entry price in the unfavorable direction. The order executes at the calculated price or a worse value. If this parameter and stop are not na, the command places a stop-loss order only at the price level expected to trigger an exit first. The default is na.loss are not na, the command places a stop-loss order only at the price level expected to trigger an exit first. The default is na.trail_points are not na, the command sets the activation level using the value expected to activate the stop first. The default is na.trail_points ticks away from the trade's entry price in the favorable direction. If the value is negative, the command creates the trailing stop immediately when the market price is equal to or more favorable than the level trail_points ticks away from the entry price in the unfavorable direction. The default is na.trail_price or trail_points parameter, or exceeds the level in the favorable direction, the command creates a trailing stop with an initial value trail_offset ticks away from that level in the unfavorable direction. After activation, the trailing stop moves toward the market price each time the trade's profit reaches a better value, maintaining the specified distance behind the best price. The default is na.oca_name executes, the strategy reduces the sizes of other unfilled orders in the OCA group by the filled quantity. The default is an empty string, which means the strategy assigns the OCA name automatically, and the resulting orders cannot reduce or be reduced by the orders from other commands.id. The command ignores this value if the call includes an argument for a comment_* parameter that applies to the order. The default is an empty string.id or comment. This comment applies only to the command's take-profit orders created using the profit or limit parameter. The default is an empty string.id or comment. This comment applies only to the command's stop-loss orders created using the loss or stop parameter. The default is an empty string.id or comment. This comment applies only to the command's trailing stop orders created using the trail_price or trail_points and trail_offset parameters. The default is an empty string.{{strategy.order.alert_message}} placeholder, the alert message replaces the placeholder with this text. The command ignores this value if the call includes an argument for the other alert_* parameter that applies to the order. The default is an empty string.{{strategy.order.alert_message}} placeholder, the alert message replaces the placeholder with this text. This message applies only to the command's take-profit orders created using the profit or limit parameter. The default is an empty string.{{strategy.order.alert_message}} placeholder, the alert message replaces the placeholder with this text. This message applies only to the command's stop-loss orders created using the loss or stop parameter. The default is an empty string.{{strategy.order.alert_message}} placeholder, the alert message replaces the placeholder with this text. This message applies only to the command's trailing stop orders created using the trail_price or trail_points and trail_offset parameters. The default is an empty string.//@version=6
strategy("Exit bracket strategy", overlay = true)
// Inputs that define the profit and loss amount of each trade as a tick distance from the entry price.
int profitDistanceInput = input.int(100, "Profit distance, in ticks", 1)
int lossDistanceInput = input.int(100, "Loss distance, in ticks", 1)
// Variables to track the take-profit and stop-loss price.
var float takeProfit = na
var float stopLoss = na
// Calculate a 14-bar and 28-bar moving average of `close` prices.
float sma14 = ta.sma(close, 14)
float sma28 = ta.sma(close, 28)
if ta.crossover(sma14, sma28) and strategy.opentrades == 0
// Place a market order to enter a long position.
strategy.entry("My Long Entry ID", strategy.long)
// Place a take-profit and stop-loss order when the entry order fills.
strategy.exit("My Long Exit ID", "My Long Entry ID", profit = profitDistanceInput, loss = lossDistanceInput)
if ta.change(strategy.opentrades) == 1
//@variable The long entry price.
float entryPrice = strategy.opentrades.entry_price(0)
// Update the `takeProfit` and `stopLoss` values.
takeProfit := entryPrice + profitDistanceInput * syminfo.mintick
stopLoss := entryPrice - lossDistanceInput * syminfo.mintick
if ta.change(strategy.closedtrades) == 1
// Reset the `takeProfit` and `stopLoss`.
takeProfit := na
stopLoss := na
// Plot the `takeProfit` and `stopLoss`.
plot(takeProfit, "Take-profit level", color.green, 2, plot.style_linebr)
plot(stopLoss, "Stop-loss level", color.red, 2, plot.style_linebr)
//@version=6
strategy("Trailing stop strategy", overlay = true)
//@variable The distance required to activate the trailing stop.
float activationDistanceInput = input.int(100, "Trail activation distance, in ticks") * syminfo.mintick
//@variable The number of ticks the trailing stop follows behind the price as it reaches new peaks.
int trailDistanceInput = input.int(100, "Trail distance, in ticks")
//@function Draws a label and line at the specified `price` to visualize a trailing stop order's activation level.
drawActivation(float price) =>
label.new(
bar_index, price, "Activation level", style = label.style_label_right,
color = color.gray, textcolor = color.white
)
line.new(
bar_index, price, bar_index + 1, price, extend = extend.right, style = line.style_dashed, color = color.gray
)
//@function Stops the `l` line from extending further.
method stopExtend(line l) =>
l.set_x2(bar_index)
l.set_extend(extend.none)
// The activation line, active trailing stop price, and active trailing stop flag.
var line activationLine = na
var float trailingStopPrice = na
var bool isActive = false
if bar_index % 100 == 0 and strategy.opentrades == 0
trailingStopPrice := na
isActive := false
// Place a market order to enter a long position.
strategy.entry("My Long Entry ID", strategy.long)
//@variable The activation level's price.
float activationPrice = close + activationDistanceInput
// Create a trailing stop order that activates the defined number of ticks above the entry price.
strategy.exit(
"My Long Exit ID", "My Long Entry ID", trail_price = activationPrice, trail_offset = trailDistanceInput,
oca_name = "Exit"
)
// Create new drawings at the `activationPrice`.
activationLine := drawActivation(activationPrice)
// Logic for trailing stop visualization.
if strategy.opentrades == 1
// Stop extending the `activationLine` when the stop activates.
if not isActive and high > activationLine.get_price(bar_index)
isActive := true
activationLine.stopExtend()
// Update the `trailingStopPrice` while the trailing stop is active.
if isActive
float offsetPrice = high - trailDistanceInput * syminfo.mintick
trailingStopPrice := math.max(nz(trailingStopPrice, offsetPrice), offsetPrice)
// Close the trade with a market order if the trailing stop does not activate before the next 300th bar.
if not isActive and bar_index % 300 == 0
strategy.close_all("Market close")
// Reset the `trailingStopPrice` and `isActive` flags when the trade closes, and stop extending the `activationLine`.
if ta.change(strategy.closedtrades) > 0
if not isActive
activationLine.stopExtend()
trailingStopPrice := na
isActive := false
// Plot the `trailingStopPrice`.
plot(trailingStopPrice, "Trailing stop", color.red, 3, plot.style_linebr)
from_entry value. If the call does not include a from_entry argument, it creates exit orders for all open trades, even the ones opened after the call, until the position closes. See this section of our User Manual to learn more.close_entries_rule in the strategy declaration statement is "FIFO" (default), the orders from a strategy.exit call exit from the position starting with the first open trade. This behavior applies even if the from_entry value is the entry ID of different open trades. However, in that case, the maximum size of the exit orders still depends on the trades opened by orders with the from_entry ID. For more information, see this section of our User Manual.strategy.opentrades.commission(trade_num) → series float
// Calculates the gross profit or loss for the current open position.
//@version=6
strategy("`strategy.opentrades.commission` Example", commission_type = strategy.commission.percent, commission_value = 0.1)
// Strategy calls to enter long trades every 15 bars and exit long trades every 20 bars.
if bar_index % 15 == 0
strategy.entry("Long", strategy.long)
if bar_index % 20 == 0
strategy.close("Long")
// Calculate gross profit or loss for open positions only.
tradeOpenGrossPL() =>
sumOpenGrossPL = 0.0
for tradeNo = 0 to strategy.opentrades - 1
sumOpenGrossPL += strategy.opentrades.profit(tradeNo) - strategy.opentrades.commission(tradeNo)
result = sumOpenGrossPL
plot(tradeOpenGrossPL())
strategy.opentrades.entry_bar_index(trade_num) → series int
// Wait 10 bars and then close the position.
//@version=6
strategy("`strategy.opentrades.entry_bar_index` Example")
barsSinceLastEntry() =>
strategy.opentrades > 0 ? bar_index - strategy.opentrades.entry_bar_index(strategy.opentrades - 1) : na
// Enter a long position if there are no open positions.
if strategy.opentrades == 0
strategy.entry("Long", strategy.long)
// Close the long position after 10 bars.
if barsSinceLastEntry() >= 10
strategy.close("Long")
trade_num.strategy.opentrades.entry_comment(trade_num) → series string
//@version=6
strategy("`strategy.opentrades.entry_comment()` Example", overlay = true)
stopPrice = open * 1.01
longCondition = ta.crossover(ta.sma(close, 14), ta.sma(close, 28))
if (longCondition)
strategy.entry("Long", strategy.long, stop = stopPrice, comment = str.tostring(stopPrice, "#.####"))
var testTable = table.new(position.top_right, 1, 3, color.orange, border_width = 1)
if barstate.islastconfirmedhistory or barstate.isrealtime
table.cell(testTable, 0, 0, 'Last entry stats')
table.cell(testTable, 0, 1, "Order stop price value: " + strategy.opentrades.entry_comment(strategy.opentrades - 1))
table.cell(testTable, 0, 2, "Actual Entry Price: " + str.tostring(strategy.opentrades.entry_price(strategy.opentrades - 1)))
strategy.opentrades.entry_id(trade_num) → series string
//@version=6
strategy("`strategy.opentrades.entry_id` Example", overlay = true)
// We enter a long position when 14 period sma crosses over 28 period sma.
// We enter a short position when 14 period sma crosses under 28 period sma.
longCondition = ta.crossover(ta.sma(close, 14), ta.sma(close, 28))
shortCondition = ta.crossunder(ta.sma(close, 14), ta.sma(close, 28))
// Strategy calls to enter a long or short position when the corresponding condition is met.
if longCondition
strategy.entry("Long entry at bar #" + str.tostring(bar_index), strategy.long)
if shortCondition
strategy.entry("Short entry at bar #" + str.tostring(bar_index), strategy.short)
// Display ID of the latest open position.
if barstate.islastconfirmedhistory
label.new(bar_index, high + (2 * ta.tr), "Last opened position is \n " + strategy.opentrades.entry_id(strategy.opentrades - 1))
strategy.opentrades.entry_price(trade_num) → series float
//@version=6
strategy("strategy.opentrades.entry_price Example 1", overlay = true)
// Strategy calls to enter long trades every 15 bars and exit long trades every 20 bars.
if ta.crossover(close, ta.sma(close, 14))
strategy.entry("Long", strategy.long)
// Return the entry price for the latest closed trade.
currEntryPrice = strategy.opentrades.entry_price(strategy.opentrades - 1)
currExitPrice = currEntryPrice * 1.05
if high >= currExitPrice
strategy.close("Long")
plot(currEntryPrice, "Long entry price", style = plot.style_linebr)
plot(currExitPrice, "Long exit price", color.green, style = plot.style_linebr)
// Calculates the average price for the open position.
//@version=6
strategy("strategy.opentrades.entry_price Example 2", pyramiding = 2)
// Strategy calls to enter long trades every 15 bars and exit long trades every 20 bars.
if bar_index % 15 == 0
strategy.entry("Long", strategy.long)
if bar_index % 20 == 0
strategy.close("Long")
// Calculates the average price for the open position.
avgOpenPositionPrice() =>
sumOpenPositionPrice = 0.0
for tradeNo = 0 to strategy.opentrades - 1
sumOpenPositionPrice += strategy.opentrades.entry_price(tradeNo) * strategy.opentrades.size(tradeNo) / strategy.position_size
result = nz(sumOpenPositionPrice / strategy.opentrades)
plot(avgOpenPositionPrice())
strategy.opentrades.entry_time(trade_num) → series int
//@version=6
strategy("strategy.opentrades.entry_time Example")
// Strategy calls to enter long trades every 15 bars and exit long trades every 20 bars.
if bar_index % 15 == 0
strategy.entry("Long", strategy.long)
if bar_index % 20 == 0
strategy.close("Long")
// Calculates duration in milliseconds since the last position was opened.
timeSinceLastEntry()=>
strategy.opentrades > 0 ? (time - strategy.opentrades.entry_time(strategy.opentrades - 1)) : na
plot(timeSinceLastEntry() / 1000 * 60 * 60 * 24, "Days since last entry")
strategy.opentrades.max_drawdown(trade_num) → series float
//@version=6
strategy("strategy.opentrades.max_drawdown Example 1")
// Strategy calls to enter long trades every 15 bars and exit long trades every 20 bars.
if bar_index % 15 == 0
strategy.entry("Long", strategy.long)
if bar_index % 20 == 0
strategy.close("Long")
// Plot the max drawdown of the latest open trade.
plot(strategy.opentrades.max_drawdown(strategy.opentrades - 1), "Max drawdown of the latest open trade")
// Calculates the max trade drawdown value for all open trades.
//@version=6
strategy("`strategy.opentrades.max_drawdown` Example 2", pyramiding = 100)
// Strategy calls to enter long trades every 15 bars and exit long trades every 20 bars.
if bar_index % 15 == 0
strategy.entry("Long", strategy.long)
if bar_index % 20 == 0
strategy.close("Long")
// Get the biggest max trade drawdown value from all of the open trades.
maxTradeDrawDown() =>
maxDrawdown = 0.0
for tradeNo = 0 to strategy.opentrades - 1
maxDrawdown := math.max(maxDrawdown, strategy.opentrades.max_drawdown(tradeNo))
result = maxDrawdown
plot(maxTradeDrawDown(), "Biggest max drawdown")
Lowest Value During Trade / (Entry Price x Quantity) * 100.strategy.opentrades.max_drawdown_percent(trade_num) → series float
strategy.opentrades.max_runup(trade_num) → series float
//@version=6
strategy("strategy.opentrades.max_runup Example 1")
// Strategy calls to enter long trades every 15 bars and exit long trades every 20 bars.
if bar_index % 15 == 0
strategy.entry("Long", strategy.long)
if bar_index % 20 == 0
strategy.close("Long")
// Plot the max runup of the latest open trade.
plot(strategy.opentrades.max_runup(strategy.opentrades - 1), "Max runup of the latest open trade")
// Calculates the max trade runup value for all open trades.
//@version=6
strategy("strategy.opentrades.max_runup Example 2", pyramiding = 100)
// Enter a long position every 30 bars.
if bar_index % 30 == 0
strategy.entry("Long", strategy.long)
// Calculate biggest max trade runup value from all of the open trades.
maxOpenTradeRunUp() =>
maxRunup = 0.0
for tradeNo = 0 to strategy.opentrades - 1
maxRunup := math.max(maxRunup, strategy.opentrades.max_runup(tradeNo))
result = maxRunup
plot(maxOpenTradeRunUp(), "Biggest max runup of all open trades")
Highest Value During Trade / (Entry Price x Quantity) * 100.strategy.opentrades.max_runup_percent(trade_num) → series float
strategy.opentrades.profit(trade_num) → series float
// Returns the profit of the last open trade.
//@version=6
strategy("`strategy.opentrades.profit` Example 1", commission_type = strategy.commission.percent, commission_value = 0.1)
// Strategy calls to enter long trades every 15 bars and exit long trades every 20 bars.
if bar_index % 15 == 0
strategy.entry("Long", strategy.long)
if bar_index % 20 == 0
strategy.close("Long")
plot(strategy.opentrades.profit(strategy.opentrades - 1), "Profit of the latest open trade")
// Calculates the profit for all open trades.
//@version=6
strategy("`strategy.opentrades.profit` Example 2", pyramiding = 5)
// Strategy calls to enter 5 long positions every 2 bars.
if bar_index % 2 == 0
strategy.entry("Long", strategy.long, qty = 5)
// Calculate open profit or loss for the open positions.
tradeOpenPL() =>
sumProfit = 0.0
for tradeNo = 0 to strategy.opentrades - 1
sumProfit += strategy.opentrades.profit(tradeNo)
result = sumProfit
plot(tradeOpenPL(), "Profit of all open trades")
strategy.opentrades.profit_percent(trade_num) → series float
strategy.opentrades.size(trade_num) → series float
//@version=6
strategy("`strategy.opentrades.size` Example 1")
// We calculate the max amt of shares we can buy.
amtShares = math.floor(strategy.equity / close)
// Strategy calls to enter long trades every 15 bars and exit long trades every 20 bars
if bar_index % 15 == 0
strategy.entry("Long", strategy.long, qty = amtShares)
if bar_index % 20 == 0
strategy.close("Long")
// Plot the number of contracts in the latest open trade.
plot(strategy.opentrades.size(strategy.opentrades - 1), "Amount of contracts in latest open trade")
// Calculates the average profit percentage for all open trades.
//@version=6
strategy("`strategy.opentrades.size` Example 2")
// Strategy calls to enter long trades every 15 bars and exit long trades every 20 bars.
if bar_index % 15 == 0
strategy.entry("Long", strategy.long)
if bar_index % 20 == 0
strategy.close("Long")
// Calculate profit for all open trades.
profitPct = 0.0
for tradeNo = 0 to strategy.opentrades - 1
entryP = strategy.opentrades.entry_price(tradeNo)
exitP = close
profitPct += (exitP - entryP) / entryP * strategy.opentrades.size(tradeNo) * 100
// Calculate average profit percent for all open trades.
avgProfitPct = nz(profitPct / strategy.opentrades)
plot(avgProfitPct)
id exists, a call to this command modifies that order.limit and stop parameters. If the call does not contain limit or stop arguments, it creates a market order that executes on the next tick. If the call specifies a limit value but no stop value, it places a limit order that executes after the market price reaches the limit value or a better price (lower for buy orders and higher for sell orders). If the call specifies a stop value but no limit value, it places a stop order that executes after the market price reaches the stop value or a worse price (higher for buy orders and lower for sell orders). If the call contains limit and stop arguments, it creates a stop-limit order, which generates a limit order at the limit price only after the market price reaches the stop value or a worse price.pyramiding parameter of the strategy declaration statement. Strategies can open any number of trades in the same direction with calls to this function.qty of 5 and a direction of strategy.short triggers the sale of five shares, which closes the position.strategy.order(id, direction, qty, limit, stop, oca_name, oca_type, comment, alert_message, disable_alert) → void
comment value.default_qty_type and default_qty_value parameters of the strategy declaration statement to determine the quantity.stop value is also specified. The default is na, which means the resulting order is not of the limit or stop-limit type.limit value is also specified. The default is na, which means the resulting order is not of the stop or stop-limit type.oca_name and oca_type parameters executes, that order affects all unfilled orders in the group. The default is an empty string, which means the order does not belong to an OCA group.oca_name and oca_type values executes. Possible values: strategy.oca.cancel, strategy.oca.reduce, strategy.oca.none. The default is strategy.oca.none.id. The default is an empty string.{{strategy.order.alert_message}} placeholder, the alert message replaces the placeholder with this text. The default is an empty string.//@version=6
strategy("Market order strategy", overlay = true)
// Calculate a 14-bar and 28-bar moving average of `close` prices.
float sma14 = ta.sma(close, 14)
float sma28 = ta.sma(close, 28)
// Place a market order to enter a long position when `sma14` crosses over `sma28`.
if ta.crossover(sma14, sma28) and strategy.position_size == 0
strategy.order("My Long Entry ID", strategy.long)
// Place a market order to sell the same quantity as the long trade when `sma14` crosses under `sma28`,
// effectively closing the long position.
if ta.crossunder(sma14, sma28) and strategy.position_size > 0
strategy.order("My Long Exit ID", strategy.short)
//@version=6
strategy("Limit and stop exit strategy", overlay = true)
//@variable The distance from the long entry price for each short limit order.
float shortOffsetInput = input.int(200, "Sell limit/stop offset, in ticks", 1) * syminfo.mintick
//@function Draws a label and line at the specified `price` to visualize a limit order's level.
drawLimit(float price, bool isLong, bool isStop = false) =>
color col = isLong ? color.blue : color.red
label.new(
bar_index, price, (isLong ? "Long " : "Short ") + (isStop ? "stop" : "limit") + " order created",
style = label.style_label_right, color = col, textcolor = color.white
)
line.new(bar_index, price, bar_index + 1, price, extend = extend.right, style = line.style_dashed, color = col)
//@function Stops the `l` line from extending further.
method stopExtend(line l) =>
l.set_x2(bar_index)
l.set_extend(extend.none)
// Initialize two `line` variables to reference limit and stop line IDs.
var line profitLimit = na
var line lossStop = na
// Calculate a 14-bar and 28-bar moving average of `close` prices.
float sma14 = ta.sma(close, 14)
float sma28 = ta.sma(close, 28)
if ta.crossover(sma14, sma28) and strategy.position_size == 0
// Place a market order to enter a long position.
strategy.order("My Long Entry ID", strategy.long)
if strategy.position_size > 0 and strategy.position_size[1] == 0
//@variable The entry price of the long trade.
float entryPrice = strategy.opentrades.entry_price(0)
// Calculate short limit and stop levels above and below the `entryPrice`.
float profitLevel = entryPrice + shortOffsetInput
float lossLevel = entryPrice - shortOffsetInput
// Place short limit and stop orders at the `profitLevel` and `lossLevel`.
strategy.order("Profit", strategy.short, limit = profitLevel, oca_name = "Bracket", oca_type = strategy.oca.cancel)
strategy.order("Loss", strategy.short, stop = lossLevel, oca_name = "Bracket", oca_type = strategy.oca.cancel)
// Make new drawings for the `profitLimit` and `lossStop` lines.
profitLimit := drawLimit(profitLevel, isLong = false)
lossStop := drawLimit(lossLevel, isLong = false, isStop = true)
if ta.change(strategy.closedtrades) > 0
// Stop extending the `profitLimit` and `lossStop` lines.
profitLimit.stopExtend()
lossStop.stopExtend()
strategy.risk.allow_entry_in(value) → void
//@version=6
strategy("strategy.risk.allow_entry_in")
strategy.risk.allow_entry_in(strategy.direction.long)
if open > close
strategy.entry("Long", strategy.long)
// Instead of opening a short position with 10 contracts, this command will close long entries.
if open < close
strategy.entry("Short", strategy.short, qty = 10)
strategy.risk.max_cons_loss_days(count, alert_message) → void
//@version=6
strategy("risk.max_cons_loss_days Demo 1")
strategy.risk.max_cons_loss_days(3) // No orders will be placed after 3 days, if each day is with loss.
plot(strategy.position_size)
strategy.risk.max_drawdown(value, type, alert_message) → void
//@version=6
strategy("risk.max_drawdown Demo 1")
strategy.risk.max_drawdown(50, strategy.percent_of_equity) // set maximum drawdown to 50% of maximum equity
plot(strategy.position_size)
//@version=6
strategy("risk.max_drawdown Demo 2", currency = "EUR")
strategy.risk.max_drawdown(2000, strategy.cash) // set maximum drawdown to 2000 EUR from maximum equity
plot(strategy.position_size)
strategy.risk.max_intraday_filled_orders(count, alert_message) → void
//@version=6
strategy("risk.max_intraday_filled_orders Demo")
strategy.risk.max_intraday_filled_orders(10) // After 10 orders are filled, no more strategy orders will be placed (except for a market order to exit current open market position, if there is any).
if open > close
strategy.entry("buy", strategy.long)
if open < close
strategy.entry("sell", strategy.short)
strategy.risk.max_intraday_loss(value, type, alert_message) → void
// Sets the maximum intraday loss using the strategy's equity value.
//@version=6
strategy("strategy.risk.max_intraday_loss Example 1", overlay = false, default_qty_type = strategy.percent_of_equity, default_qty_value = 100)
// Input for maximum intraday loss %.
lossPct = input.float(10)
// Set maximum intraday loss to our lossPct input
strategy.risk.max_intraday_loss(lossPct, strategy.percent_of_equity)
// Enter Short at bar_index zero.
if bar_index == 0
strategy.entry("Short", strategy.short)
// Store equity value from the beginning of the day
eqFromDayStart = ta.valuewhen(ta.change(dayofweek) > 0, strategy.equity, 0)
// Calculate change of the current equity from the beginning of the current day.
eqChgPct = 100 * ((strategy.equity - eqFromDayStart) / strategy.equity)
// Plot it
plot(eqChgPct)
hline(-lossPct)
// Sets the maximum intraday loss using the strategy's cash value.
//@version=6
strategy("strategy.risk.max_intraday_loss Example 2", overlay = false)
// Input for maximum intraday loss in absolute cash value of the symbol.
absCashLoss = input.float(5)
// Set maximum intraday loss to `absCashLoss` in account currency.
strategy.risk.max_intraday_loss(absCashLoss, strategy.cash)
// Enter Short at bar_index zero.
if bar_index == 0
strategy.entry("Short", strategy.short)
// Store the open price value from the beginning of the day.
beginPrice = ta.valuewhen(ta.change(dayofweek) > 0, open, 0)
// Calculate the absolute price change for the current period.
priceChg = (close - beginPrice)
hline(absCashLoss)
plot(priceChg)
strategy.risk.max_position_size(contracts) → void
//@version=6
strategy("risk.max_position_size Demo", default_qty_value = 100)
strategy.risk.max_position_size(10)
if open > close
strategy.entry("buy", strategy.long)
plot(strategy.position_size) // max plot value will be 10
string(x) → const string
string(x) → input string
string(x) → simple string
string(x) → series string
symbol, e.g. "NASDAQ".syminfo.prefix(symbol) → simple string
syminfo.prefix(symbol) → series string
//@version=6
indicator("syminfo.prefix fun", overlay=true)
i_sym = input.symbol("NASDAQ:AAPL")
pref = syminfo.prefix(i_sym)
tick = syminfo.ticker(i_sym)
t = ticker.new(pref, tick, session.extended)
s = request.security(t, "1D", close)
plot(s)
symbol, e.g. "NASDAQ".symbol name without exchange prefix, e.g. "AAPL".syminfo.ticker(symbol) → simple string
syminfo.ticker(symbol) → series string
//@version=6
indicator("syminfo.ticker fun", overlay=true)
i_sym = input.symbol("NASDAQ:AAPL")
pref = syminfo.prefix(i_sym)
tick = syminfo.ticker(i_sym)
t = ticker.new(pref, tick, session.extended)
s = request.security(t, "1D", close)
plot(s)
symbol name without exchange prefix, e.g. "AAPL".ta.alma(series, length, offset, sigma, floor) → series float
//@version=6
indicator("ta.alma", overlay=true)
plot(ta.alma(close, 9, 0.85, 6))
// same on pine, but much less efficient
pine_alma(series, windowsize, offset, sigma) =>
m = offset * (windowsize - 1)
//m = math.floor(offset * (windowsize - 1)) // Used as m when math.floor=true
s = windowsize / sigma
norm = 0.0
sum = 0.0
for i = 0 to windowsize - 1
weight = math.exp(-1 * math.pow(i - m, 2) / (2 * math.pow(s, 2)))
norm := norm + weight
sum := sum + series[windowsize - i - 1] * weight
sum / norm
plot(pine_alma(close, 9, 0.85, 6))
na values in the source series are included in calculations and will produce an na result.ta.atr(length) → series float
//@version=6
indicator("ta.atr")
plot(ta.atr(14))
//the same on pine
pine_atr(length) =>
trueRange = na(high[1])? high-low : math.max(math.max(high - low, math.abs(high - close[1])), math.abs(low - close[1]))
//true range can be also calculated with ta.tr(true)
ta.rma(trueRange, length)
plot(pine_atr(14))
na values in the source series are ignored; the function calculates on the length quantity of non-na values.ta.barssince(condition) → series int
//@version=6
indicator("ta.barssince")
// get number of bars since last color.green bar
plot(ta.barssince(close >= open))
ta.bb(series, length, mult) → [series float, series float, series float]
//@version=6
indicator("ta.bb")
[middle, upper, lower] = ta.bb(close, 5, 4)
plot(middle, color=color.yellow)
plot(upper, color=color.yellow)
plot(lower, color=color.yellow)
// the same on pine
f_bb(src, length, mult) =>
float basis = ta.sma(src, length)
float dev = mult * ta.stdev(src, length)
[basis, basis + dev, basis - dev]
[pineMiddle, pineUpper, pineLower] = f_bb(close, 5, 4)
plot(pineMiddle)
plot(pineUpper)
plot(pineLower)
na values in the source series are ignored; the function calculates on the length quantity of non-na values.ta.bbw(series, length, mult) → series float
//@version=6
indicator("ta.bbw")
plot(ta.bbw(close, 5, 4), color=color.yellow)
// the same on pine
f_bbw(src, length, mult) =>
float basis = ta.sma(src, length)
float dev = mult * ta.stdev(src, length)
(((basis + dev) - (basis - dev)) / basis) * 100
plot(f_bbw(close, 5, 4))
na values in the source series are ignored; the function calculates on the length quantity of non-na values.ta.cci(source, length) → series float
na values in the source series are ignored.source value to its value length bars ago and returns the difference.ta.change(source, length) → series int
ta.change(source, length) → series float
ta.change(source, length) → series bool
source value is offset from the current one, in bars. Optional. The default is 1.//@version=6
indicator('Day and Direction Change', overlay = true)
dailyBarTime = time('1D')
isNewDay = ta.change(dailyBarTime) != 0
bgcolor(isNewDay ? color.new(color.green, 80) : na)
isGreenBar = close >= open
colorChange = ta.change(isGreenBar)
plotshape(colorChange, 'Direction Change')
true when the current source is different from the previous source.na values in the source series are included in calculations and will produce an na result.ta.cmo(series, length) → series float
//@version=6
indicator("ta.cmo")
plot(ta.cmo(close, 5), color=color.yellow)
// the same on pine
f_cmo(src, length) =>
float mom = ta.change(src)
float sm1 = math.sum((mom >= 0) ? mom : 0.0, length)
float sm2 = math.sum((mom >= 0) ? 0.0 : -mom, length)
100 * (sm1 - sm2) / (sm1 + sm2)
plot(f_cmo(close, 5))
na values in the source series are ignored.ta.cog(source, length) → series float
//@version=6
indicator("ta.cog", overlay=true)
plot(ta.cog(close, 10))
// the same on pine
pine_cog(source, length) =>
sum = math.sum(source, length)
num = 0.0
for i = 0 to length - 1
price = source[i]
num := num + price * (i + 1)
-num / sum
plot(pine_cog(close, 10))
na values in the source series are ignored.ta.correlation(source1, source2, length) → series float
na values in the source series are ignored; the function calculates on the length quantity of non-na values.ta.cross(source1, source2) → series bool
source1-series is defined as having crossed over source2-series if, on the current bar, the value of source1 is greater than the value of source2, and on the previous bar, the value of source1 was less than or equal to the value of source2.ta.crossover(source1, source2) → series bool
source1 crossed over source2 otherwise false.source1-series is defined as having crossed under source2-series if, on the current bar, the value of source1 is less than the value of source2, and on the previous bar, the value of source1 was greater than or equal to the value of source2.ta.crossunder(source1, source2) → series bool
source1 crossed under source2 otherwise false.source. In other words it's a sum of all elements of source.ta.cum(source) → series float
ta.dev(source, length) → series float
//@version=6
indicator("ta.dev")
plot(ta.dev(close, 10))
// the same on pine
pine_dev(source, length) =>
mean = ta.sma(source, length)
sum = 0.0
for i = 0 to length - 1
val = source[i]
sum := sum + math.abs(val - mean)
dev = sum/length
plot(pine_dev(close, 10))
source for length bars back.na values in the source series are ignored.ta.dmi(diLength, adxSmoothing) → [series float, series float, series float]
//@version=6
indicator(title="Directional Movement Index", shorttitle="DMI", format=format.price, precision=4)
len = input.int(17, minval=1, title="DI Length")
lensig = input.int(14, title="ADX Smoothing", minval=1)
[diplus, diminus, adx] = ta.dmi(len, lensig)
plot(adx, color=color.red, title="ADX")
plot(diplus, color=color.blue, title="+DI")
plot(diminus, color=color.orange, title="-DI")
EMA = alpha * source + (1 - alpha) * EMA[1], where alpha = 2 / (length + 1).ta.ema(source, length) → series float
//@version=6
indicator("ta.ema")
plot(ta.ema(close, 15))
//the same on pine
pine_ema(src, length) =>
alpha = 2 / (length + 1)
sum = 0.0
sum := na(sum[1]) ? src : alpha * src + (1 - alpha) * nz(sum[1])
plot(pine_ema(close,15))
source with alpha = 2 / (length + 1).na values in the source series are ignored; the function calculates on the length quantity of non-na values.source series is now falling for length bars long.ta.falling(source, length) → series bool
source value is less than any previous source value for length bars back, false otherwise.na values in the source series are ignored; the function calculates on the length quantity of non-na values.ta.highest(source, length) → series float
source is a series and length is the number of bars back.length is the number of bars back. Algorithm uses high as a source series.na values in the source series are ignored.ta.highestbars(source, length) → series int
source is a series and length is the number of bars back.length is the number of bars back. Algorithm uses high as a source series.na values in the source series are ignored.ta.hma(source, length) → series float
//@version=6
indicator("Hull Moving Average")
src = input(defval=close, title="Source")
length = input(defval=9, title="Length")
hmaBuildIn = ta.hma(src, length)
plot(hmaBuildIn, title="Hull MA", color=#674EA7)
na values in the source series are ignored.ta.kc(series, length, mult, useTrueRange) → [series float, series float, series float]
//@version=6
indicator("ta.kc")
[middle, upper, lower] = ta.kc(close, 5, 4)
plot(middle, color=color.yellow)
plot(upper, color=color.yellow)
plot(lower, color=color.yellow)
// the same on pine
f_kc(src, length, mult, useTrueRange) =>
float basis = ta.ema(src, length)
float span = (useTrueRange) ? ta.tr : (high - low)
float rangeEma = ta.ema(span, length)
[basis, basis + rangeEma * mult, basis - rangeEma * mult]
[pineMiddle, pineUpper, pineLower] = f_kc(close, 5, 4, true)
plot(pineMiddle)
plot(pineUpper)
plot(pineLower)
na values in the source series are ignored; the function calculates on the length quantity of non-na values.ta.kcw(series, length, mult, useTrueRange) → series float
//@version=6
indicator("ta.kcw")
plot(ta.kcw(close, 5, 4), color=color.yellow)
// the same on pine
f_kcw(src, length, mult, useTrueRange) =>
float basis = ta.ema(src, length)
float span = (useTrueRange) ? ta.tr : (high - low)
float rangeEma = ta.ema(span, length)
((basis + rangeEma * mult) - (basis - rangeEma * mult)) / basis
plot(f_kcw(close, 5, 4, true))
na values in the source series are ignored; the function calculates on the length quantity of non-na values.source series.ta.linreg(source, length, offset) → series float
na values in the source series are included in calculations and will produce an na result.ta.lowest(source, length) → series float
source is a series and length is the number of bars back.length is the number of bars back. Algorithm uses low as a source series.na values in the source series are ignored.ta.lowestbars(source, length) → series int
source is a series and length is the number of bars back.length is the number of bars back. Algorithm uses low as a source series.na values in the source series are ignored.ta.macd(source, fastlen, slowlen, siglen) → [series float, series float, series float]
//@version=6
indicator("MACD")
[macdLine, signalLine, histLine] = ta.macd(close, 12, 26, 9)
plot(macdLine, color=color.blue)
plot(signalLine, color=color.orange)
plot(histLine, color=color.red, style=plot.style_histogram)
//@version=6
indicator("MACD")
[_, signalLine, _] = ta.macd(close, 12, 26, 9)
plot(signalLine, color=color.orange)
na values in the source series are ignored; the function calculates on the length quantity of non-na values.source from the beginning of the chart up to the current bar.ta.max(source) → series float
source are ignored.ta.median(source, length) → series int
ta.median(source, length) → series float
na values in the source series are ignored; the function calculates on the length quantity of non-na values.ta.mfi(series, length) → series float
//@version=6
indicator("Money Flow Index")
plot(ta.mfi(hlc3, 14), color=color.yellow)
// the same on pine
pine_mfi(src, length) =>
float upper = math.sum(volume * (ta.change(src) <= 0.0 ? 0.0 : src), length)
float lower = math.sum(volume * (ta.change(src) >= 0.0 ? 0.0 : src), length)
mfi = 100.0 - (100.0 / (1.0 + upper / lower))
mfi
plot(pine_mfi(hlc3, 14))
na values in the source series are ignored; the function calculates on the length quantity of non-na values.source from the beginning of the chart up to the current bar.ta.min(source) → series float
source are ignored.ta.mode(source, length) → series int
ta.mode(source, length) → series float
source. If none exists, returns the smallest value instead.na values in the source series are ignored; the function calculates on the length quantity of non-na values.source price and source price length bars ago. This is simply a difference: source - source[length].ta.mom(source, length) → series float
source price and source price length bars ago.na values in the source series are included in calculations and will produce an na result.ta.percentile_linear_interpolation(source, length, percentage) → series float
source series for length bars back.na values in the source series are included in calculations and will produce an na result.ta.percentile_nearest_rank(source, length, percentage) → series float
source series for length bars back.na values in the source series are ignored.ta.percentrank(source, length) → series float
source for length bars back.na values in the source series are included in calculations and will produce an na result.type and anchor.ta.pivot_point_levels(type, anchor, developing) → array<float>
//@version=6
indicator("Weekly Pivots", max_lines_count=500, overlay=true)
timeframe = "1W"
typeInput = input.string("Traditional", "Type", options=["Traditional", "Fibonacci", "Woodie", "Classic", "DM", "Camarilla"])
weekChange = timeframe.change(timeframe)
pivotPointsArray = ta.pivot_point_levels(typeInput, weekChange)
if weekChange
for pivotLevel in pivotPointsArray
line.new(time, pivotLevel, time + timeframe.in_seconds(timeframe) * 1000, pivotLevel, xloc=xloc.bar_time)
array<float> with numerical values representing 11 pivot point levels: [P, R1, S1, R2, S2, R3, S3, R4, S4, R5, S5]. Levels absent from the specified type return na values (e.g., "DM" only calculates P, R1, and S1).developing parameter cannot be true when type is set to "Woodie", because the Woodie calculation for a period depends on that period's open, which means that the pivot value is either available or unavailable, but never developing. If used together, the indicator will return a runtime error.ta.pivothigh(leftbars, rightbars) → series float
ta.pivothigh(source, leftbars, rightbars) → series float
//@version=6
indicator("PivotHigh", overlay=true)
leftBars = input(2)
rightBars=input(2)
ph = ta.pivothigh(leftBars, rightBars)
plot(ph, style=plot.style_cross, linewidth=3, color= color.red, offset=-rightBars)
ta.pivotlow(leftbars, rightbars) → series float
ta.pivotlow(source, leftbars, rightbars) → series float
//@version=6
indicator("PivotLow", overlay=true)
leftBars = input(2)
rightBars=input(2)
pl = ta.pivotlow(close, leftBars, rightBars)
plot(pl, style=plot.style_cross, linewidth=3, color= color.blue, offset=-rightBars)
ta.range(source, length) → series int
ta.range(source, length) → series float
na values in the source series are ignored; the function calculates on the length quantity of non-na values.source series and the bar index over length bars using Spearman's rank correlation coefficient. The resulting value is scaled to a range of -100 to 100, where 100 indicates the source consistently increased over the period, and -100 indicates it consistently decreased. Values between -100 and 100 reflect varying degrees of upward or downward consistency.ta.rci(source, length) → series float
source series is now rising for length bars long.ta.rising(source, length) → series bool
source is greater than any previous source for length bars back, false otherwise.na values in the source series are ignored.ta.rma(source, length) → series float
//@version=6
indicator("ta.rma")
plot(ta.rma(close, 15))
//the same on pine
pine_rma(src, length) =>
alpha = 1/length
sum = 0.0
sum := na(sum[1]) ? ta.sma(src, length) : alpha * src + (1 - alpha) * nz(sum[1])
plot(pine_rma(close, 15))
source with alpha = 1 / length.na values in the source series are ignored; the function calculates on the length quantity of non-na values.source and its value length bars ago.ta.roc(source, length) → series float
source for length bars back.na values in the source series are included in calculations and will produce an na result.ta.rma() of upward and downward changes of source over the last length bars.ta.rsi(source, length) → series float
//@version=6
indicator("ta.rsi")
plot(ta.rsi(close, 7))
// same on pine, but less efficient
pine_rsi(x, y) =>
u = math.max(x - x[1], 0) // upward ta.change
d = math.max(x[1] - x, 0) // downward ta.change
rs = ta.rma(u, y) / ta.rma(d, y)
res = 100 - 100 / (1 + rs)
res
plot(pine_rsi(close, 7))
na values in the source series are ignored; the function calculates on the length quantity of non-na values.ta.sar(start, inc, max) → series float
//@version=6
indicator("ta.sar")
plot(ta.sar(0.02, 0.02, 0.2), style=plot.style_cross, linewidth=3)
// The same on Pine Script®
pine_sar(start, inc, max) =>
var float result = na
var float maxMin = na
var float acceleration = na
var bool isBelow = false
bool isFirstTrendBar = false
if bar_index == 1
if close > close[1]
isBelow := true
maxMin := high
result := low[1]
else
isBelow := false
maxMin := low
result := high[1]
isFirstTrendBar := true
acceleration := start
result := result + acceleration * (maxMin - result)
if isBelow
if result > low
isFirstTrendBar := true
isBelow := false
result := math.max(high, maxMin)
maxMin := low
acceleration := start
else
if result < high
isFirstTrendBar := true
isBelow := true
result := math.min(low, maxMin)
maxMin := high
acceleration := start
if not isFirstTrendBar
if isBelow
if high > maxMin
maxMin := high
acceleration := math.min(acceleration + inc, max)
else
if low < maxMin
maxMin := low
acceleration := math.min(acceleration + inc, max)
if isBelow
result := math.min(result, low[1])
if bar_index > 1
result := math.min(result, low[2])
else
result := math.max(result, high[1])
if bar_index > 1
result := math.max(result, high[2])
result
plot(pine_sar(0.02, 0.02, 0.2), style=plot.style_cross, linewidth=3)
ta.sma(source, length) → series float
//@version=6
indicator("ta.sma")
plot(ta.sma(close, 15))
// same on pine, but much less efficient
pine_sma(x, y) =>
sum = 0.0
for i = 0 to y - 1
sum := sum + x[i] / y
sum
plot(pine_sma(close, 15))
source for length bars back.na values in the source series are ignored.ta.stdev(source, length, biased) → series float
//@version=6
indicator("ta.stdev")
plot(ta.stdev(close, 5))
//the same on pine
isZero(val, eps) => math.abs(val) <= eps
SUM(fst, snd) =>
EPS = 1e-10
res = fst + snd
if isZero(res, EPS)
res := 0
else
if not isZero(res, 1e-4)
res := res
else
15
pine_stdev(src, length) =>
avg = ta.sma(src, length)
sumOfSquareDeviations = 0.0
for i = 0 to length - 1
sum = SUM(src[i], -avg)
sumOfSquareDeviations := sumOfSquareDeviations + sum * sum
stdev = math.sqrt(sumOfSquareDeviations / length)
plot(pine_stdev(close, 5))
biased is true, function will calculate using a biased estimate of the entire population, if false - unbiased estimate of a sample.na values in the source series are ignored; the function calculates on the length quantity of non-na values.ta.stoch(source, high, low, length) → series float
na values in the source series are ignored.ta.supertrend(factor, atrPeriod) → [series float, series float]
//@version=6
indicator("Pine Script® Supertrend")
[supertrend, direction] = ta.supertrend(3, 10)
plot(direction < 0 ? supertrend : na, "Up direction", color = color.green, style=plot.style_linebr)
plot(direction > 0 ? supertrend : na, "Down direction", color = color.red, style=plot.style_linebr)
// The same on Pine Script®
pine_supertrend(factor, atrPeriod) =>
src = hl2
atr = ta.atr(atrPeriod)
upperBand = src + factor * atr
lowerBand = src - factor * atr
prevLowerBand = nz(lowerBand[1])
prevUpperBand = nz(upperBand[1])
lowerBand := lowerBand > prevLowerBand or close[1] < prevLowerBand ? lowerBand : prevLowerBand
upperBand := upperBand < prevUpperBand or close[1] > prevUpperBand ? upperBand : prevUpperBand
int _direction = na
float superTrend = na
prevSuperTrend = superTrend[1]
if na(atr[1])
_direction := 1
else if prevSuperTrend == prevUpperBand
_direction := close > upperBand ? -1 : 1
else
_direction := close < lowerBand ? 1 : -1
superTrend := _direction == -1 ? lowerBand : upperBand
[superTrend, _direction]
[Pine_Supertrend, pineDirection] = pine_supertrend(3, 10)
plot(pineDirection < 0 ? Pine_Supertrend : na, "Up direction", color = color.green, style=plot.style_linebr)
plot(pineDirection > 0 ? Pine_Supertrend : na, "Down direction", color = color.red, style=plot.style_linebr)
ta.swma(source) → series float
//@version=6
indicator("ta.swma")
plot(ta.swma(close))
// same on pine, but less efficient
pine_swma(x) =>
x[3] * 1 / 6 + x[2] * 2 / 6 + x[1] * 2 / 6 + x[0] * 1 / 6
plot(pine_swma(close))
na values in the source series are included in calculations and will produce an na result.high - low), true range accounts for potential gaps by taking the maximum of the current bar's actual range and the absolute distances from the previous bar's close to the current bar's high and low. The formula is: math.max(high - low, math.abs(high - close[1]), math.abs(low - close[1]))ta.tr(handle_na) → series float
high - low value. If false, it returns na.ta.tsi(source, short_length, long_length) → series float
na values in the source series are ignored; the function calculates on the length quantity of non-na values.source series on the bar where the condition was true on the nth most recent occurrence.ta.valuewhen(condition, source, occurrence) → series color
ta.valuewhen(condition, source, occurrence) → series int
ta.valuewhen(condition, source, occurrence) → series float
ta.valuewhen(condition, source, occurrence) → series bool
condition, '1' is the second most recent and so forth. Must be an integer >= 0.//@version=6
indicator("ta.valuewhen")
slow = ta.sma(close, 7)
fast = ta.sma(close, 14)
// Get value of `close` on second most recent cross
plot(ta.valuewhen(ta.cross(slow, fast), close, 1))
ta.variance(source, length, biased) → series float
source for length bars back.biased is true, function will calculate using a biased estimate of the entire population, if false - unbiased estimate of a sample.na values in the source series are ignored; the function calculates on the length quantity of non-na values.ta.vwap(source, anchor) → series float
ta.vwap(source, anchor, stdev_mult) → [series float, series float, series float]
//@version=6
indicator("Simple VWAP")
vwap = ta.vwap(open)
plot(vwap)
//@version=6
indicator("Advanced VWAP")
vwapAnchorInput = input.string("Daily", "Anchor", options = ["Daily", "Weekly", "Monthly"])
stdevMultiplierInput = input.float(1.0, "Standard Deviation Multiplier")
anchorTimeframe = switch vwapAnchorInput
"Daily" => "1D"
"Weekly" => "1W"
"Monthly" => "1M"
anchor = timeframe.change(anchorTimeframe)
[vwap, upper, lower] = ta.vwap(open, anchor, stdevMultiplierInput)
plot(vwap)
plot(upper, color = color.green)
plot(lower, color = color.green)
stdev_mult is specified.source for length bars back. It is the same as: sma(source * volume, length) / sma(volume, length).ta.vwma(source, length) → series float
//@version=6
indicator("ta.vwma")
plot(ta.vwma(close, 15))
// same on pine, but less efficient
pine_vwma(x, y) =>
ta.sma(x * volume, y) / ta.sma(volume, y)
plot(pine_vwma(close, 15))
source for length bars back.na values in the source series are ignored.source for length bars back. In wma weighting factors decrease in arithmetical progression.ta.wma(source, length) → series float
//@version=6
indicator("ta.wma")
plot(ta.wma(close, 15))
// same on pine, but much less efficient
pine_wma(x, y) =>
norm = 0.0
sum = 0.0
for i = 0 to y - 1
weight = (y - i) * y
norm := norm + weight
sum := sum + x[i] * weight
sum / norm
plot(pine_wma(close, 15))
source for length bars back.na values in the source series are ignored.ta.wpr(length) → series float
//@version=6
indicator("Williams %R", shorttitle="%R", format=format.price, precision=2)
plot(ta.wpr(14), title="%R", color=color.new(#ff6d00, 0))
na values in the source series are ignored.table.cell(table_id, column, row, text, width, height, text_color, text_halign, text_valign, text_size, bgcolor, tooltip, text_font_family, text_formatting) → void
text.format_bold + text.format_italic will make the text both bold and italicized. Possible values: text.format_none, text.format_bold, text.format_italic. Optional. The default is text.format_none.table.cell_set_bgcolor(table_id, column, row, bgcolor) → void
table.cell_set_height(table_id, column, row, height) → void
table.cell_set_text(table_id, column, row, text) → void
//@version=6
indicator("TABLE example")
var tLog = table.new(position = position.top_left, rows = 1, columns = 2, bgcolor = color.yellow, border_width=1)
table.cell(tLog, row = 0, column = 0, text = "sometext", text_color = color.blue)
table.cell_set_text(tLog, row = 0, column = 0, text = "sometext")
table.cell_set_text_color(table_id, column, row, text_color) → void
table.cell_set_text_font_family(table_id, column, row, text_font_family) → void
//@version=6
indicator("Example of setting the table cell font")
var t = table.new(position.top_left, rows = 1, columns = 1)
table.cell(t, 0, 0, "monospace", text_color = color.blue)
table.cell_set_text_font_family(t, 0, 0, font.family_monospace)
table.cell_set_text_formatting(table_id, column, row, text_formatting) → void
text.format_bold + text.format_italic will make the text both bold and italicized. Possible values: text.format_none, text.format_bold, text.format_italic. Optional. The default is text.format_none.table.cell_set_text_halign(table_id, column, row, text_halign) → void
table.cell_set_text_size(table_id, column, row, text_size) → void
table.cell_set_text_valign(table_id, column, row, text_valign) → void
table.cell_set_tooltip(table_id, column, row, tooltip) → void
//@version=6
indicator("TABLE example")
var tLog = table.new(position = position.top_left, rows = 1, columns = 2, bgcolor = color.yellow, border_width=1)
table.cell(tLog, row = 0, column = 0, text = "sometext", text_color = color.blue)
table.cell_set_tooltip(tLog, row = 0, column = 0, tooltip = "sometext")
table.cell_set_width(table_id, column, row, width) → void
table.clear(table_id, start_column, start_row, end_column, end_row) → void
//@version=6
indicator("A donut", overlay=true)
if barstate.islast
colNum = 8, rowNum = 8
padding = "◯"
donutTable = table.new(position.middle_right, colNum, rowNum)
for c = 0 to colNum - 1
for r = 0 to rowNum - 1
table.cell(donutTable, c, r, text=padding, bgcolor=#face6e, text_color=color.new(color.black, 100))
table.clear(donutTable, 2, 2, 5, 5)
table.delete(table_id) → void
//@version=6
indicator("table.delete example")
var testTable = table.new(position = position.top_right, columns = 2, rows = 1, bgcolor = color.yellow, border_width = 1)
if barstate.islast
table.cell(table_id = testTable, column = 0, row = 0, text = "Open is " + str.tostring(open))
table.cell(table_id = testTable, column = 1, row = 0, text = "Close is " + str.tostring(close), bgcolor=color.teal)
if barstate.isrealtime
table.delete(testTable)
table.merge_cells(table_id, start_column, start_row, end_column, end_row) → void
//@version=6
indicator("table.merge_cells example")
SMA50 = ta.sma(close, 50)
SMA100 = ta.sma(close, 100)
SMA200 = ta.sma(close, 200)
if barstate.islast
maTable = table.new(position.bottom_right, 3, 3, bgcolor = color.gray, border_width = 1, border_color = color.black)
// Header
table.cell(maTable, 0, 0, text = "SMA Table")
table.merge_cells(maTable, 0, 0, 2, 0)
// Cell Titles
table.cell(maTable, 0, 1, text = "SMA 50")
table.cell(maTable, 1, 1, text = "SMA 100")
table.cell(maTable, 2, 1, text = "SMA 200")
// Values
table.cell(maTable, 0, 2, bgcolor = color.white, text = str.tostring(SMA50))
table.cell(maTable, 1, 2, bgcolor = color.white, text = str.tostring(SMA100))
table.cell(maTable, 2, 2, bgcolor = color.white, text = str.tostring(SMA200))
start_column:start_row, except width and height. The width and height of the resulting merged cell are based on the width/height of other cells in the neighboring columns/rows and cannot be set manually.table.cell_set_* functions, target the cell at the start_column:start_row coordinates.table.new(position, columns, rows, bgcolor, frame_color, frame_width, border_color, border_width, force_overlay) → series table
//@version=6
indicator("table.new example")
var testTable = table.new(position = position.top_right, columns = 2, rows = 1, bgcolor = color.yellow, border_width = 1)
if barstate.islast
table.cell(table_id = testTable, column = 0, row = 0, text = "Open is " + str.tostring(open))
table.cell(table_id = testTable, column = 1, row = 0, text = "Close is " + str.tostring(close), bgcolor=color.teal)
table.set_bgcolor(table_id, bgcolor) → void
table.set_border_color(table_id, border_color) → void
table.set_border_width(table_id, border_width) → void
table.set_frame_color(table_id, frame_color) → void
table.set_frame_width(table_id, frame_width) → void
table.set_position(table_id, position) → void
ticker.heikinashi(symbol) → simple string
ticker.heikinashi(symbol) → series string
//@version=6
indicator("ticker.heikinashi", overlay=true)
heikinashi_close = request.security(ticker.heikinashi(syminfo.tickerid), timeframe.period, close)
heikinashi_aapl_60_close = request.security(ticker.heikinashi("AAPL"), "60", close)
plot(heikinashi_close)
plot(heikinashi_aapl_60_close)
symbol with additional parameters inherited from the ticker ID passed into the function call, allowing the script to request a symbol's data using the same modifiers that the from_tickerid has, including extended session, dividend adjustment, currency conversion, non-standard chart types, back-adjustment, settlement-as-close, etc.ticker.inherit(from_tickerid, symbol) → simple string
ticker.inherit(from_tickerid, symbol) → series string
//@version=6
indicator("ticker.inherit")
//@variable A "NASDAQ:AAPL" ticker ID with Extender Hours enabled.
tickerExtHours = ticker.new("NASDAQ", "AAPL", session.extended)
//@variable A Heikin Ashi ticker ID for "NASDAQ:AAPL" with Extended Hours enabled.
HAtickerExtHours = ticker.heikinashi(tickerExtHours)
//@variable The "NASDAQ:MSFT" symbol with no modifiers.
testSymbol = "NASDAQ:MSFT"
//@variable A ticker ID for "NASDAQ:MSFT" with inherited Heikin Ashi and Extended Hours modifiers.
testSymbolHAtickerExtHours = ticker.inherit(HAtickerExtHours, testSymbol)
//@variable The `close` price requested using "NASDAQ:MSFT" with inherited modifiers.
secData = request.security(testSymbolHAtickerExtHours, "60", close, ignore_invalid_symbol = true)
//@variable The `close` price requested using "NASDAQ:MSFT" without modifiers.
compareData = request.security(testSymbol, "60", close, ignore_invalid_symbol = true)
plot(secData, color = color.green)
plot(compareData)
from_tickerid has Extended Hours enabled, but no such option is available for the symbol), the script will ignore the modifier when requesting data using the ID.ticker.kagi(symbol, reversal) → simple string
ticker.kagi(symbol, reversal) → series string
ticker.kagi(symbol, param, style) → simple string
ticker.kagi(symbol, param, style) → series string
//@version=6
indicator("ticker.kagi", overlay=true)
kagi_tickerid = ticker.kagi(syminfo.tickerid, 3)
kagi_close = request.security(kagi_tickerid, timeframe.period, close)
plot(kagi_close)
ticker.linebreak(symbol, number_of_lines) → simple string
ticker.linebreak(symbol, number_of_lines) → series string
//@version=6
indicator("ticker.linebreak", overlay=true)
linebreak_tickerid = ticker.linebreak(syminfo.tickerid, 3)
linebreak_close = request.security(linebreak_tickerid, timeframe.period, close)
plot(linebreak_close)
ticker.modify(tickerid, session, adjustment, backadjustment, settlement_as_close) → simple string
ticker.modify(tickerid, session, adjustment, backadjustment, settlement_as_close) → series string
tickerid parameter, or it inherits the symbol's default if the tickerid does not specify this setting. Possible values: backadjustment.inherit, backadjustment.on, backadjustment.off.tickerid passed into the function, or it inherits the chart symbol's default if the tickerid does not specify this setting. Possible values: settlement_as_close.inherit, settlement_as_close.on, settlement_as_close.off.//@version=6
indicator("ticker_modify", overlay=true)
t1 = ticker.new(syminfo.prefix, syminfo.ticker, session.regular, adjustment.splits)
c1 = request.security(t1, "D", close)
t2 = ticker.modify(t1, session.extended)
c2 = request.security(t2, "2D", close)
plot(c1)
plot(c2)
ticker.new(prefix, ticker, session, adjustment, backadjustment, settlement_as_close) → simple string
ticker.new(prefix, ticker, session, adjustment, backadjustment, settlement_as_close) → series string
//@version=6
indicator("ticker.new", overlay=true)
t = ticker.new(syminfo.prefix, syminfo.ticker, session.regular, adjustment.splits)
t2 = ticker.heikinashi(t)
c = request.security(t2, timeframe.period, low, barmerge.gaps_on)
plot(c, style=plot.style_linebr)
ticker.pointfigure(symbol, source, style, param, reversal) → simple string
ticker.pointfigure(symbol, source, style, param, reversal) → series string
style value is "ATR", "Box size" value if the style is "Traditional", or "Percentage" value if the style is "PercentageLTP". //@version=6
indicator("ticker.pointfigure", overlay=true)
pnf_tickerid = ticker.pointfigure(syminfo.tickerid, "hl", "Traditional", 1, 3)
pnf_close = request.security(pnf_tickerid, timeframe.period, close)
plot(pnf_close)
ticker.renko(symbol, style, param, request_wicks, source) → simple string
ticker.renko(symbol, style, param, request_wicks, source) → series string
style value is "ATR", "Box size" value if the style is "Traditional", or "Percentage" value if the style is "PercentageLTP". //@version=6
indicator("ticker.renko", overlay=true)
renko_tickerid = ticker.renko(syminfo.tickerid, "ATR", 10)
renko_close = request.security(renko_tickerid, timeframe.period, close)
plot(renko_close)
//@version=6
indicator("Renko candles", overlay=false)
renko_tickerid = ticker.renko(syminfo.tickerid, "ATR", 10)
[renko_open, renko_high, renko_low, renko_close] = request.security(renko_tickerid, timeframe.period, [open, high, low, close])
plotcandle(renko_open, renko_high, renko_low, renko_close, color = renko_close > renko_open ? color.green : color.red)
ticker.standard(symbol) → simple string
ticker.standard(symbol) → series string
//@version=6
indicator("ticker.standard", overlay = true)
// This script should be run on a non-standard chart such as HA, Renko...
// Requests data from the chart type the script is running on.
chartTypeValue = request.security(syminfo.tickerid, "1D", close)
// Request data from the standard chart type, regardless of the chart type the script is running on.
standardChartValue = request.security(ticker.standard(syminfo.tickerid), "1D", close)
// This will not use a standard ticker ID because the `symbol` argument contains only the ticker — not the prefix (exchange).
standardChartValue2 = request.security(ticker.standard(syminfo.ticker), "1D", close)
plot(chartTypeValue)
plot(standardChartValue, color = color.green)
symbol argument does not contain the prefix and ticker information, the function returns the supplied argument as is.time(timeframe, session, bars_back) → series int
time(timeframe, session, timezone, bars_back) → series int
//@version=6
indicator("Time", overlay=true)
// Try this on chart AAPL,1
timeinrange(res, sess) => not na(time(res, sess, "America/New_York")) ? 1 : 0
plot(timeinrange("1", "1300-1400"), color=color.red)
// This plots 1.0 at every start of 10 minute bar on a 1 minute chart:
newbar(res) => ta.change(time(res)) == 0 ? 0 : 1
plot(newbar("10"))
//@version=6
indicator("Time", overlay=true)
t1 = time(timeframe.period, "0000-0000:23456")
bgcolor(not na(t1) ? color.new(color.blue, 90) : na)
session argument can include several different sessions, separated by commas. For example, the following script will highlight the bars from 10:00 to 11:00 and from 14:00 to 15:00 (workdays only)://@version=6
indicator("Time", overlay=true)
t1 = time(timeframe.period, "1000-1100,1400-1500:23456")
bgcolor(not na(t1) ? color.new(color.blue, 90) : na)
time_close(timeframe, session, bars_back) → series int
time_close(timeframe, session, timezone, bars_back) → series int
//@version=6
indicator("Time", overlay=true)
t1 = time_close(timeframe.period, "1200-1300", "America/New_York")
bgcolor(not na(t1) ? color.new(color.blue, 90) : na)
timeframe.timeframe.change(timeframe) → series bool
//@version=6
// Run this script on an intraday chart.
indicator("New day started", overlay = true)
// Highlights the first bar of the new day.
isNewDay = timeframe.change("1D")
bgcolor(isNewDay ? color.new(color.green, 80) : na)
timeframe.from_seconds(seconds) → simple string
timeframe.from_seconds(seconds) → series string
//@version=6
indicator("HTF Close", "", true)
int chartTf = timeframe.in_seconds()
string tfTimes5 = timeframe.from_seconds(chartTf * 5)
float htfClose = request.security(syminfo.tickerid, tfTimes5, close)
plot(htfClose)
timeframe.in_seconds(timeframe) → simple int
timeframe.in_seconds(timeframe) → series int
//@version=6
indicator("`timeframe_in_seconds()`"),
// Get a user-selected timeframe.
tfInput = input.timeframe("1D")
// Convert it into an "int" number of seconds.
secondsInTf = timeframe.in_seconds(tfInput)
plot(secondsInTf)
timestamp(dateString) → const int
timestamp(dateString) → series int
timestamp(year, month, day, hour, minute, second) → simple int
timestamp(year, month, day, hour, minute, second) → series int
timestamp(timezone, year, month, day, hour, minute, second) → simple int
timestamp(timezone, year, month, day, hour, minute, second) → series int
//@version=6
indicator("timestamp")
plot(timestamp(2016, 01, 19, 09, 30), linewidth=3, color=color.green)
plot(timestamp(syminfo.timezone, 2016, 01, 19, 09, 30), color=color.blue)
plot(timestamp(2016, 01, 19, 09, 30), color=color.yellow)
plot(timestamp("GMT+6", 2016, 01, 19, 09, 30))
plot(timestamp(2019, 06, 19, 09, 30, 15), color=color.lime)
plot(timestamp("GMT+3", 2019, 06, 19, 09, 30, 15), color=color.fuchsia)
plot(timestamp("Feb 01 2020 22:10:05"))
plot(timestamp("2011-10-10T14:48:00"))
plot(timestamp("04 Dec 1995 00:12:00 GMT+5"))
weekofyear(time, timezone) → series int
year(time, timezone) → series int
const string title. Scripts can access the fields in an enum using dot notation, similar to accessing the fields of a user-defined type.enumName enum. Scripts can declare each field in an enum with an optional const string title. If a field's title is not specified, its title is the string representation of its name. Use str.tostring on an enum field to retrieve its title.[export ]enum <enumName> <field_1> [= <title_1>] <field_2> [= <title_2>] ... <field_N> [= <title_N>]
//@version=6
indicator("Session highlight", overlay = true)
//@enum Contains fields with popular timezones as titles.
//@field exch Has an empty string as the title to represent the chart timezone.
enum tz
utc = "UTC"
exch = ""
ny = "America/New_York"
chi = "America/Chicago"
lon = "Europe/London"
tok = "Asia/Tokyo"
//@variable The session string.
selectedSession = input.session("1200-1500", "Session")
//@variable The selected timezone. The input's dropdown contains the fields in the `tz` enum.
selectedTimezone = input.enum(tz.utc, "Session Timezone")
//@variable Is `true` if the current bar's time is in the specified session.
bool inSession = false
if not na(time("", selectedSession, str.tostring(selectedTimezone)))
inSession := true
// Highlight the background when `inSession` is `true`.
bgcolor(inSession ? color.new(color.green, 90) : na, title = "Active session highlight")
//@version=6
indicator("Map with enum keys")
//@enum Contains fields with titles representing ticker IDs.
//@field aapl Has an Apple ticker ID as its title.
//@field tsla Has a Tesla ticker ID as its title.
//@field amzn Has an Amazon ticker ID as its title.
enum symbols
aapl = "NASDAQ:AAPL"
tsla = "NASDAQ:TSLA"
amzn = "NASDAQ:AMZN"
//@variable A map that accepts fields from the `symbols` enum as keys and "float" values.
map<symbols, float> data = map.new<symbols, float>()
// Put key-value pairs into the `data` map.
data.put(symbols.aapl, request.security(str.tostring(symbols.aapl), timeframe.period, close))
data.put(symbols.tsla, request.security(str.tostring(symbols.tsla), timeframe.period, close))
data.put(symbols.amzn, request.security(str.tostring(symbols.amzn), timeframe.period, close))
// Plot the value from the `data` map accessed by the `symbols.aapl` key.
plot(data.get(symbols.aapl))
//@version=6
//@description Library of debugging functions.
library("Debugging_library", overlay = true)
//@function Displays a string as a table cell for debugging purposes.
//@param txt String to display.
//@returns Void.
export print(string txt) =>
var table t = table.new(position.middle_right, 1, 1)
table.cell(t, 0, 0, txt, bgcolor = color.yellow)
// Using the function from inside the library to show an example on the published chart.
// This has no impact on scripts using the library.
print("Library Test")
:=), or variables of 'input' form.request.*() functions.[variables =|:=] for counter = from_num to to_num [by step_num]
statements | continue | break
return_expressionreturn_expression after the loop terminates. The script can assign the loop's returned results to variables only if the results are not "void". If the loop's conditions prevent iteration, or if no iterations evaluate the return_expression, the variables' assigned values and references are na.from_num) to the final value (to_num) by a fixed amount (step_num) after each iteration. The last possible iteration occurs when the variable's value reaches the to_num value.counter variable on the loop's first iteration.counter value for which the loop's header allows a new iteration. The loop increments the counter value by the step_num until it reaches or passes this value. If the script modifies this value during a loop iteration, the loop header uses the new value to control the allowed subsequent iterations.counter value increases or decreases until it reaches or passes the to_num value. If the from_num value is greater than the initial to_num value, the loop subtracts this amount from the counter value after each iteration. Otherwise, the loop adds this amount after each iteration. The default is 1.continue or break statement, the returned values or references are those of the latest iteration that evaluated this code. To use the loop's returned results, assign them to a variable or tuple.//@version=6
indicator("Basic `for` loop")
//@function Calculates the number of bars in the last `length` bars that have their `close` above the current `close`.
//@param length The number of bars used in the calculation.
greaterCloseCount(length) =>
int result = 0
for i = 1 to length
if close[i] > close
result += 1
result
plot(greaterCloseCount(14))
//@version=6
indicator("`for` loop with a step")
a = array.from(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
sum = 0.0
for i = 0 to 9 by 5
// Because the step is set to 5, we are adding only the first (0) and the sixth (5) value from the array `a`.
sum += array.get(a, i)
plot(sum)
to_num value during an iteration does not change the direction of the loop's counter. For a loop that counts upward, setting the to_num to a value less than the from_num value on an iteration stops the loop immediately after that iteration ends. Likewise, a loop that counts downward stops after an iteration where the to_num value becomes greater than the from_num value.for...in structure allows the repeated execution of a number of statements for each element in an array. It can be used with either one argument: array_element, or with two: [index, array_element]. The second form doesn't affect the functionality of the loop. It tracks the current iteration's index in the tuple's first variable.[var_declaration =] for array_element in array_id
statements | continue | break
return_expression
[var_declaration =] for [index, array_element] in array_id
statements | continue | break
return_expressionreturn_expression.array_element.var_declaration, if one is present. If the loop exits because of a 'continue' or 'break' keyword, the loop's return value is that of the last variable assigned a value before the loop's exit.for...in loop, iterate over the key-value pairs of a copy or over the elements in its map.keys array.for...in to determine on each bar how many of the bar's OHLC values are greater than the SMA of 'close' values://@version=6
indicator("for...in")
// Here we determine on each bar how many of the bar's OHLC values are greater than the SMA of 'close' values
float[] ohlcValues = array.from(open, high, low, close)
qtyGreaterThan(value, array) =>
int result = 0
for currentElement in array
if currentElement > value
result += 1
result
plot(qtyGreaterThan(ta.sma(close, 20), ohlcValues))
isPos array to true when their corresponding value in our valuesArray array is positive://@version=6
indicator("for...in")
var valuesArray = array.from(4, -8, 11, 78, -16, 34, 7, 99, 0, 55)
var isPos = array.new_bool(10, false)
for [index, value] in valuesArray
if value > 0
array.set(isPos, index, true)
if barstate.islastconfirmedhistory
label.new(bar_index, high, str.tostring(isPos))
//@version=6
indicator("`for ... in` matrix Example")
// Create a 2x3 matrix with values `4`.
matrix1 = matrix.new<int>(2, 3, 4)
sum = 0.0
// Loop through every row of the matrix.
for rowArray in matrix1
// Sum values of the every row
sum += array.sum(rowArray)
plot(sum)
var_declarationX = if condition
var_decl_then0
var_decl_then1
…
var_decl_thenN
else if [optional block]
var_decl_else0
var_decl_else1
…
var_decl_elseN
else
var_decl_else0
var_decl_else1
…
var_decl_elseN
return_expression_else//@version=6
indicator("if")
// This code compiles
x = if close > open
close
else
open
// This code doesn’t compile
// y = if close > open
// close
// else
// "open"
plot(x)
else block. In this case if the condition is false, an “empty” value (na, false, or “”) will be assigned to the var_declarationX variable://@version=6
indicator("if")
x = if close > open
close
// If current close > current open, then x = close.
// Otherwise the x = na.
plot(x)
//@version=6
indicator("if")
x = if open > close
5
else if high > low
close
else
open
plot(x)
if statement (“var_declarationX=“ can be omitted). It may be useful if you need the side effect of the expression, for example in strategy trading://@version=6
strategy("if")
if (ta.crossover(high, low))
strategy.entry("BBandLE", strategy.long, stop=low, oca_name="BollingerBands", oca_type=strategy.oca.cancel, comment="BBandLE")
else
strategy.cancel(id="BBandLE")
//@version=6
indicator("if")
float x = na
if close > open
if close > close[1]
x := close
else
x := close[1]
else
x := open
plot(x)
import {username}/{libraryName}/{libraryVersion} as {alias}title argument used by the author in his library script.libraryName string.//@version=6
indicator("num_methods import")
// Import the first version of the username’s "num_methods" library and assign it to the "m" namespace",
import username/num_methods/1 as m
// Call the “sinh()” function from the imported library
y = m.sinh(3.14)
// Plot value returned by the "sinh()" function",
plot(y)
username, libraryName, or alias identifiers.[export] method <functionName>(<paramType> <paramName> [= <defaultValue>], …) =>
<functionBlock>//@version=6
indicator("")
var prices = array.new<float>()
//@function Pushes a new value into the array and removes the first one if the resulting array is greater than `maxSize`. Can be used as a method.
method maintainArray(array<float> id, maxSize, value) =>
id.push(value)
if id.size() > maxSize
id.shift()
prices.maintainArray(50, close)
// The method can also be called like a function, without using dot notation.
// In this case an argument must be supplied for its first parameter.
// maintainArray(prices, 50, close)
// This calls the `array.avg()` built-in using dot notation with the `prices` array.
// It is possible because built-in functions belonging to some namespaces that are a special Pine type
// can be invoked with method notation when the function's first parameter is an ID of that type.
// Those namespaces are: `array`, `matrix`, `line`, `linefill`, `label`, `box`, and `table`.
plot(prices.avg())
not expr1
[variable_declaration = ] switch expression
value1 => local_block
value2 => local_block
…
=> default_local_block
[variable_declaration = ] switch
condition1 => local_block
condition2 => local_block
…
=> default_local_block//@version=6
indicator("Switch using an expression")
string i_maType = input.string("EMA", "MA type", options = ["EMA", "SMA", "RMA", "WMA"])
float ma = switch i_maType
"EMA" => ta.ema(close, 10)
"SMA" => ta.sma(close, 10)
"RMA" => ta.rma(close, 10)
// Default used when the three first cases do not match.
=> ta.wma(close, 10)
plot(ma)
//@version=6
strategy("Switch without an expression", overlay = true)
bool longCondition = ta.crossover( ta.sma(close, 14), ta.sma(close, 28))
bool shortCondition = ta.crossunder(ta.sma(close, 14), ta.sma(close, 28))
switch
longCondition => strategy.entry("Long ID", strategy.long)
shortCondition => strategy.entry("Short ID", strategy.short)
local_block instances or the default_local_block can be executed. The default_local_block is introduced with the => token alone and is only executed when none of the preceding blocks are executed. If the result of the switch statement is assigned to a variable and a default_local_block is not specified, the statement returns na if no local_block is executed. When assigning the result of the switch statement to a variable, all local_block instances must return the same type of value.[export ]type <UDT_identifier>
[varip ]<field_type> <field_name> [= <value>]
…UDT_identifier.new() construct. When creating a new type instance, the fields of the resulting object will initialize with the default values from the UDT's definition. Any type fields without specified defaults will initialize as na. Alternatively, users can pass initial values as arguments in the *.new() method to override the type's defaults. For example, newFooObject = foo.new(x = true) assigns a new foo object to the newFooObject variable with its x field initialized using a value of true.//@version=6
indicator("Multi Time Period Chart", overlay = true)
timeframeInput = input.timeframe("1D")
type bar
float o = open
float h = high
float l = low
float c = close
int t = time
drawBox(bar b, right) =>
bar s = bar.new()
color boxColor = b.c >= b.o ? color.green : color.red
box.new(b.t, b.h, right, b.l, boxColor, xloc = xloc.bar_time, bgcolor = color.new(boxColor, 90))
updateBox(box boxId, bar b) =>
color boxColor = b.c >= b.o ? color.green : color.red
box.set_border_color(boxId, boxColor)
box.set_bgcolor(boxId, color.new(boxColor, 90))
box.set_top(boxId, b.h)
box.set_bottom(boxId, b.l)
box.set_right(boxId, time)
secBar = request.security(syminfo.tickerid, timeframeInput, bar.new())
if not na(secBar)
// To avoid a runtime error, only process data when an object exists.
if not barstate.islast
if timeframe.change(timeframeInput)
// On historical bars, draw a new box in the past when the HTF closes.
drawBox(secBar, time[1])
else
var box lastBox = na
if na(lastBox) or timeframe.change(timeframeInput)
// On the last bar, only draw a new current box the first time we get there or when HTF changes.
lastBox := drawBox(secBar, time)
else
// On other chart updates, use setters to modify the current box.
updateBox(lastBox, secBar)
var variable_name = expression
//@version=6
indicator("Var keyword example")
var a = close
var b = 0.0
var c = 0.0
var green_bars_count = 0
if close > open
var x = close
b := x
green_bars_count := green_bars_count + 1
if green_bars_count >= 10
var y = close
c := y
plot(a)
plot(b)
plot(c)
varip [<variable_type> ]<variable_name> = <expression>
[export ]type <UDT_identifier>
varip <field_type> <field_name> [= <value>]//@version=6
indicator("varip")
varip int v = -1
v := v + 1
plot(v)
v would equal the value of the bar_index. On historical bars, where the script calculates only once per chart bar, the value of v is the same as with var. However, on realtime bars, the script will evaluate the expression on each new chart update, producing a different result.//@version=6
indicator("varip with types")
type barData
int index = -1
varip int ticks = -1
var currBar = barData.new()
currBar.index += 1
currBar.ticks += 1
// Will be equal to bar_index on all bars
plot(currBar.index)
// In real time, will increment per every tick on the chart
plot(currBar.ticks)
index and ticks fields results in different real-time values because ticks increases on every chart update, while index only does so once per bar. Note how the currBar object does not use the varip keyword. The ticks field of the object can increment on every tick, but the reference itself is defined once and then stays unchanged. If we were to declare currBar using varip, the behavior of index would remain unchanged because while the reference to the type instance would persist between chart updates, the index field of the object would not.while statement allows the conditional iteration of a local code block.variable_declaration = while condition
…
continue
…
break
…
return_expressionreturn expression can provide the initialization value for this variable.while statement is executed. When false, execution of the script resumes after the while statement.continue keyword causes the loop to branch to its next iteration.break keyword causes the loop to terminate. The script's execution resumes after the while statement.while statement's returning value.//@version=6
indicator("while")
// This is a simple example of calculating a factorial using a while loop.
int i_n = input.int(10, "Factorial Size", minval=0)
int counter = i_n
int factorial = 1
while counter > 0
factorial := factorial * counter
counter := counter - 1
plot(factorial)
while line must be indented with four spaces or a tab. For the while loop to terminate, the boolean expression following while must eventually become false, or a break must be executed.//@version=6
indicator("array", overlay=true)
array<float> a = na
a := array.new<float>(1, close)
plot(array.get(a, 0))
//@version=6
indicator("bool")
bool b = true // Same as `b = true`
plot(b ? open : close)
//@version=6
indicator("box")
// Empty `box1` box ID.
var box box1 = na
// `box` type is unnecessary because `box.new()` returns a "box" type.
var box2 = box.new(na, na, na, na)
box3 = box.new(time, open, time + 60 * 60 * 24, close, xloc=xloc.bar_time)
chart.point. Scripts can produce chart.point instances using the chart.point.from_time, chart.point.from_index, chart.point.now, and chart.point.new functions.//@version=6
indicator("color", overlay = true)
color textColor = color.green
color labelColor = #FF000080 // Red color (FF0000) with 50% transparency (80 which is half of FF).
if barstate.islastconfirmedhistory
label.new(bar_index, high, text = "Label", color = labelColor, textcolor = textColor)
// When declaring variables with color literals, built-in constants(color.green) or functions (color.new(), color.rgb()), the "color" keyword for the type can be omitted.
c = color.rgb(0,255,0,0)
plot(close, color = c)
const keyword explicitly assigns the "const" type qualifier to variables and the parameters of non-exported functions. Variables and parameters with the "const" qualifier reference values established at compile time that never change in the script's execution.const keyword restricts the type qualifier to "const", meaning the variable cannot accept a value with a stronger qualifier (e.g., "input"), nor can the value assigned to the variable change at any point in the script's execution.[method ]<functionName>([const <paramType> ]<paramName>[ = <defaultValue>]) [var/varip ]const <variableType> <variableName> = <variableValue>
//@version=6
indicator("custom plot title")
//@function Concatenates two "const string" values.
concatStrings(const string x, const string y) =>
const string result = x + y
//@variable The title of the plot.
const string myTitle = concatStrings("My ", "Plot")
plot(close, myTitle)
//@version=6
indicator("can't assign input to const")
//@variable A variable declared as "const float" that attempts to assign the result of `input.float()` as its value.
// This declaration causes an error. The "input float" qualified type is stronger than "const float".
const float myVar = input.float(2.0)
plot(myVar)
//@version=6
indicator("float")
float f = 3.14 // Same as `f = 3.14`
f := na
plot(f)
//@version=6
indicator("int")
int i = 14 // Same as `i = 14`
i := na
plot(i)
//@version=6
indicator("label")
// Empty `label1` label ID.
var label label1 = na
// `label` type is unnecessary because `label.new()` returns "label" type.
var label2 = label.new(na, na, na)
if barstate.islastconfirmedhistory
label3 = label.new(bar_index, high, text = "label3 text")
//@version=6
indicator("line")
// Empty `line1` line ID.
var line line1 = na
// `line` type is unnecessary because `line.new()` returns "line" type.
var line2 = line.new(na, na, na, na)
line3 = line.new(bar_index - 1, high, bar_index, high, extend = extend.right)
//@version=6
indicator("linefill", overlay=true)
// Empty `linefill1` line ID.
var linefill linefill1 = na
// `linefill` type is unnecessary because `linefill.new()` returns "linefill" type.
var linefill2 = linefill.new(na, na, na)
if barstate.islastconfirmedhistory
line1 = line.new(bar_index - 10, high+1, bar_index, high+1, extend = extend.right)
line2 = line.new(bar_index - 10, low+1, bar_index, low+1, extend = extend.right)
linefill3 = linefill.new(line1, line2, color = color.new(color.green, 80))
//@version=6
indicator("map", overlay=true)
map<int, float> a = na
a := map.new<int, float>()
a.put(bar_index, close)
label.new(bar_index, a.get(bar_index), "Current close")
//@version=6
indicator("matrix example")
// Create `m1` matrix of `int` type.
matrix<int> m1 = matrix.new<int>(2, 3, 0)
// `matrix<int>` is unnecessary because the `matrix.new<int>()` function returns an `int` type matrix object.
m2 = matrix.new<int>(2, 3, 0)
// Display matrix using a label.
if barstate.islastconfirmedhistory
label.new(bar_index, high, str.tostring(m2))
polyline. Scripts can produce polyline instances using the polyline.new function.series keyword explicitly assigns the "series" type qualifier to variables and function parameters. Variables and parameters that use the "series" qualifier can reference values that change throughout a script's execution.series keyword when declaring the parameters of a library's exported functions is typically unnecessary, as the compiler can usually automatically detect whether a parameter is compatible with "series" or "simple" qualified values. By default, all exported function parameters are qualified as "series" wherever possible.series keyword restricts the type qualifier to "series", meaning the script cannot pass its value to any variable or function parameter that requires a value with a weaker qualifier ("const", "input", or "simple").export [method ]<functionName>([[series ]<paramType>] <paramName>[ = <defaultValue>]) [method ]<functionName>([series <paramType> ]<paramName>[ = <defaultValue>]) [var/varip ]series <variableType> <variableName> = <variableValue>
//@version=6
//@description A library with custom functions.
library("CustomFunctions", overlay = true)
//@function Finds the highest `source` value over `length` bars, filtered by the `cond` condition.
export conditionalHighest(series float source, series bool cond, series int length) =>
//@variable The highest `source` value from when the `cond` was `true` over `length` bars.
series float result = na
// Loop to find the highest value.
for i = 0 to length - 1
if cond[i]
value = source[i]
result := math.max(nz(result, value), value)
// Return the `result`.
result
//@variable Is `true` once every five bars.
series bool condition = bar_index % 5 == 0
//@variable The highest `close` value from every fifth bar over the last 100 bars.
series float hiValue = conditionalHighest(close, condition, 100)
plot(hiValue)
bgcolor(condition ? color.new(color.teal, 80) : na)
//@version=6
indicator("series variable not allowed")
//@variable A variable declared as "series int" with a value of 5.
series int myVar = 5
// This call causes an error.
// The `histbase` accepts "input int/float". It can't accept the stronger "series int" qualified type.
plot(close, style = plot.style_histogram, histbase = myVar)
simple keyword explicitly assigns the "simple" type qualifier to variables and function parameters. Variables and parameters that use the "simple" qualifier can reference values established at the beginning of a script's execution that do not change later.simple keyword when declaring parameters is often necessary, as libraries automatically qualify all parameters as "series" wherever possible by default. Explicitly restricting functions to accept "simple" arguments also allows them to return "simple" values in some cases, depending on the operations they execute, making them usable with the parameters of built-in functions that do not allow "series" arguments.simple keyword restricts the type qualifier to "simple", meaning the script cannot pass its value to any variable or function parameter that requires a value with a weaker qualifier ("const" or "input"). Additionally, one cannot assign a "series" value to a variable explicitly declared with the simple keyword.export [method ]<functionName>([[simple ]<paramType>] <paramName>[ = <defaultValue>]) [method ]<functionName>([simple <paramType> ]<paramName>[ = <defaultValue>]) [var/varip ]simple <variableType> <variableName> = <variableValue></variableValue>
//@version=6
//@description A library with custom functions.
library("CustomFunctions", overlay = true)
//@function Calculates the length values for a ribbon of four EMAs by multiplying the `baseLength`.
//@param baseLength The initial EMA length. Requires "simple int" because you can't use "series int" in `ta.ema()`.
//@returns A tuple of length values.
export ribbonLengths(simple int baseLength) =>
simple int length1 = baseLength
simple int length2 = baseLength * 2
simple int length3 = baseLength * 3
simple int length4 = baseLength * 4
[length1, length2, length3, length4]
// Get a tuple of "simple int" length values.
[len1, len2, len3, len4] = ribbonLengths(14)
// Plot four EMAs using the values from the tuple.
plot(ta.ema(close, len1), "EMA 1", color = color.red)
plot(ta.ema(close, len2), "EMA 1", color = color.orange)
plot(ta.ema(close, len3), "EMA 1", color = color.green)
plot(ta.ema(close, len4), "EMA 1", color = color.blue)
//@version=6
indicator("can't change simple to series")
//@variable A variable declared as "simple float" with a value of 5.0.
simple float myVar = 5.0
// This reassignment causes an error.
// The `close` variable returns a "series float" value. Since `myVar` is restricted to "simple" values, it cannot
// change its qualifier to "series".
myVar := close
plot(myVar)
//@version=6
indicator("string")
string s = "Hello World!" // Same as `s = "Hello world!"`
// string s = na // same as ""
plot(na, title=s)
//@version=6
indicator("table")
// Empty `table1` table ID.
var table table1 = na
// `table` type is unnecessary because `table.new()` returns "table" type.
var table2 = table.new(position.top_left, na, na)
if barstate.islastconfirmedhistory
var table3 = table.new(position = position.top_right, columns = 1, rows = 1, bgcolor = color.yellow, border_width = 1)
table.cell(table_id = table3, column = 0, row = 0, text = "table3 text")
expr1 - expr2
- returns expr1 minus expr2.- returns the negation of expr.expr1 -= expr2
//@version=6
indicator("-=")
// Equals to expr1 = expr1 - expr2.
a = 2
b = 3
a -= b
// Result: a = -1.
plot(a)
<var_name> := <new_value>
//@version=6
indicator("My script")
myVar = 10
if close > open
// Modifies the existing global scope `myVar` variable by changing its value from 10 to 20.
myVar := 20
// Creates a new `myVar` variable local to the `if` condition and unreachable from the global scope.
// Does not affect the `myVar` declared in global scope.
myVar = 30
plot(myVar)
expr1 != expr2
expr1 ? expr2 : expr3
//@version=6
indicator("?:")
// Draw circles at the bars where open crosses close
s2 = ta.cross(open, close) ? math.avg(open,close) : na
plot(s2, style=plot.style_circles, linewidth=2, color=color.red)
// Combination of ?: operators for 'switch'-like logic
c = timeframe.isintraday ? color.red : timeframe.isdaily ? color.green : timeframe.isweekly ? color.blue : color.gray
plot(hl2, color=c)
expr1[expr2]
//@version=6
indicator("[]")
// [] can be used to "save" variable value between bars
a = 0.0 // declare `a`
a := a[1] // immediately set current value to the same as previous. `na` in the beginning of history
if high == low // if some condition - change `a` value to another
a := low
plot(a)
expr1 * expr2
expr1 *= expr2
//@version=6
indicator("*=")
// Equals to expr1 = expr1 * expr2.
a = 2
b = 3
a *= b
// Result: a = 6.
plot(a)
expr1 / expr2
expr1 /= expr2
//@version=6
indicator("/=")
// Equals to expr1 = expr1 / expr2.
float a = 3.0
b = 3
a /= b
// Result: a = 1.
plot(a)
expr1 % expr2
-1 % 9 = -1 - 9 * int(-1/9) = -1 - 9 * int(-0.111) = -1 - 9 * 0 = -1.expr1 %= expr2
//@version=6
indicator("%=")
// Equals to expr1 = expr1 % expr2.
a = 3
b = 3
a %= b
// Result: a = 0.
plot(a)
expr1 + expr2
+ for strings returns concatenation of expr1 and expr2+ returns expr1 plus expr2.+ returns expr (does nothing added just for the symmetry with the unary - operator).expr1 += expr2
//@version=6
indicator("+=")
// Equals to expr1 = expr1 + expr2.
a = 2
b = 3
a += b
// Result: a = 5.
plot(a)
expr1 < expr2
expr1 <= expr2
expr1 == expr2
<identifier>([<parameter_name>[=<default_value>]], ...) =>
<local_block>
<function_result>//@version=6
indicator("=>")
// single-line function
f1(x, y) => x + y
// multi-line function
f2(x, y) =>
sum = x + y
sumChange = ta.change(sum, 10)
// Function automatically returns the last expression used in it
plot(f1(30, 8) + f2(1, 3))
expr1 > expr2
expr1 >= expr2
//@version=6
// @description Provides a tool to quickly output a label on the chart.
library("MyLibrary")
// @function Outputs a label with `labelText` on the bar's high.
// @param labelText (series string) The text to display on the label.
// @returns Drawn label.
export drawLabel(string labelText) =>
label.new(bar_index, high, text = labelText)
//@version=6
indicator("Session highlight", overlay = true)
//@enum Contains fields with popular timezones as titles.
//@field exch Has an empty string as the title to represent the chart timezone.
enum tz
utc = "UTC"
exch = ""
ny = "America/New_York"
chi = "America/Chicago"
lon = "Europe/London"
tok = "Asia/Tokyo"
//@variable The session string.
selectedSession = input.session("1200-1500", "Session")
//@variable The selected timezone. The input's dropdown contains the fields in the `tz` enum.
selectedTimezone = input.enum(tz.utc, "Session Timezone")
//@variable Is `true` if the current bar's time is in the specified session.
bool inSession = false
if not na(time("", selectedSession, str.tostring(selectedTimezone)))
inSession := true
// Highlight the background when `inSession` is `true`.
bgcolor(inSession ? color.new(color.green, 90) : na, title = "Active session highlight")
//@version=6
indicator("New high over the last 20 bars", overlay = true)
//@type A point on a chart.
//@field index The index of the bar where the point is located, i.e., its `x` coordinate.
//@field price The price where the point is located, i.e., its `y` coordinate.
type Point
int index
float price
//@variable If the current `high` is the highest over the last 20 bars, returns a new `Point` instance, `na` otherwise.
Point highest = na
if ta.highestbars(high, 20) == 0
highest := Point.new(bar_index, high)
label.new(highest.index, highest.price, str.tostring(highest.price))
//@version=6
// @description Provides a tool to quickly output a label on the chart.
library("MyLibrary")
// @function Outputs a label with `labelText` on the bar's high.
// @param labelText (series string) The text to display on the label.
// @returns Drawn label.
export drawLabel(string labelText) =>
label.new(bar_index, high, text = labelText)
//@version=6
// @description Provides a tool to quickly output a label on the chart.
library("MyLibrary")
// @function Outputs a label with `labelText` on the bar's high.
// @param labelText (series string) The text to display on the label.
// @returns Drawn label.
export drawLabel(string labelText) =>
label.new(bar_index, high, text = labelText)
//@version=6
// @description Provides a tool to quickly output a label on the chart.
library("MyLibrary")
// @function Outputs a label with `labelText` on the bar's high.
// @param labelText (series string) The text to display on the label.
// @returns Drawn label.
export drawLabel(string labelText) =>
label.new(bar_index, high, text = labelText)
//@version=6
strategy("My strategy", overlay=true, margin_long=100, margin_short=100)
//@strategy_alert_message Strategy alert on symbol {{ticker}}
longCondition = ta.crossover(ta.sma(close, 14), ta.sma(close, 28))
if (longCondition)
strategy.entry("My Long Entry Id", strategy.long)
strategy.exit("Exit", "My Long Entry Id", profit = 10 / syminfo.mintick, loss = 10 / syminfo.mintick)
//@version=6
indicator("New high over the last 20 bars", overlay = true)
//@type A point on a chart.
//@field index The index of the bar where the point is located, i.e., its `x` coordinate.
//@field price The price where the point is located, i.e., its `y` coordinate.
type Point
int index
float price
//@variable If the current `high` is the highest over the last 20 bars, returns a new `Point` instance, `na` otherwise.
Point highest = na
if ta.highestbars(high, 20) == 0
highest := Point.new(bar_index, high)
label.new(highest.index, highest.price, str.tostring(highest.price))
//@version=6
indicator("New high over the last 20 bars", overlay = true)
//@type A point on a chart.
//@field index The index of the bar where the point is located, i.e., its `x` coordinate.
//@field price The price where the point is located, i.e., its `y` coordinate.
type Point
int index
float price
//@variable If the current `high` is the highest over the last 20 bars, returns a new `Point` instance, `na` otherwise.
Point highest = na
if ta.highestbars(high, 20) == 0
highest := Point.new(bar_index, high)
label.new(highest.index, highest.price, str.tostring(highest.price))
//@version=6
indicator("Pine v6 Indicator")
plot(close)
//This indicator has no version annotation, so it will try to use v1.
//Pine Script® v1 has no function named `indicator()`, so the script will not compile.
indicator("Pine v1 Indicator")
plot(close)